程序化内容生成框架(PCG)是用于在虚幻引擎中创建你自己的程序化内容和工具的工具集。 借助PCG,技术美术师、设计师和程序员能够构建任意复杂度的快速迭代式工具和内容,从资产工具(如建筑物或群系生成等)到整个世界,不一而足。
重要概念和术语
点(Points):3D空间中的坐标点,由PCG图表生成,常用于生成网格体。 点包含变换、边界、颜色、密度、陡度和种子等信息。 可以为它们分配由用户自定义的属性值。
点密度(Point Density):各种图表节点使用的值。 在调试视图中表示为每个点上的梯度,代表该点存在于该位置的概率。 例如密度0为黑色,密度1为白色。
必要设置
程序化内容生成框架要求你在项目中启用程序化内容生成框架(Procedural Content Generation Framework)插件。 如需详细了解如何启用插件,请参阅使用插件。
要在静态网格体上对点取样,需要用到程序化内容生成框架几何体脚本交互(Procedural Content Generation Framework Geometry Script Interop)插件。
程序化节点图表
程序化节点图表是程序化内容生成框架的核心部分。
和材质编辑器类似,空间数据被传入关卡中的PCG组件中的图表,然后生成点。 然后,点会经过一系列节点的筛选和修改,并输出实时更新的结果。 生成的点可用于生成各种资产。
创建PCG图表资产
要创建PCG图表资产,请执行下面的步骤:
右键点击内容侧滑菜单(Content Drawer)或内容浏览器(Content Browser),找到创建的高级资产(Create Advanced Asset)> PCG,并选择PCG图表(PCG Graph)。
选择新资产的名称,然后按Enter键。
PCG图表模版
创建PCG图表后,你可以将图表标记为模板。当你创建新图表时,就可以在上下文菜单中选择该模板。 与Niagara模板类似,你可以使用PCG图表模板加快工作流程,而不是用空白图表从头开始。
将PCG图表设为模版
要将PCG图表定义为模板,请打开该图表并执行以下步骤:
在工具栏中,点击图表设置(Graph Settings)按钮,从而在细节面板中填充图表的设置。
找到细节面板的"资产信息(Asset Info)"分段,并启用"Is Template"属性。
这时你的图表就被定义为了模板图表。
使用模版新建图表
在创建新图表并选择了资产名称和位置之后,你现在就可以在从模板创建图表(Create Graph From Template)窗口中选择一个图表模板。 选择要使用的图表模板,然后点击从模板初始化(Initialize From Template)按钮,即可使用该模板创建一个新图表。
编辑PCG图表
在PCG图表编辑器中,你可以配置并编辑PCG图表资产。 该编辑器的操作方式与蓝图或材质编辑器相似。 它还包含一些只有PCG才有的工具和面板。
| 编号 | 说明 |
|---|---|
1 | 工具栏 |
2 | 节点控制板 |
3 | 视口 |
4 | 细节面板 |
5 | 调试树 |
6 | 特性列表 |
你可以像使用蓝图那样将节点添加到图表中,方法是从节点控制板将其拖入视口中,或通过右键菜单添加。
当PCG图表被指定到PCG组件并且已用于生成内容时,对该图表所做的更改会在编辑器视口中实时更新。
PCG节点
PCG图表由一系列PCG节点构成,每个节点执行对最终结果有贡献的操作。
这些节点划分为以下类别:
| 类别 | 说明 |
|---|---|
蓝图(Blueprint) | 包含与蓝图相关的节点。 这包括用于执行从PCGBlueprintElement派生的用户蓝图的通用节点。 |
控制流程(Control Flow) | 包含负责控制图表中逻辑流程的节点。 |
调试(Debug) | 包含帮助调试的节点。 |
密度(Density) | 包含影响点密度的节点。 |
筛选器(Filter) | 包含基于条件或按点筛选数据的节点。 |
通用(Generic) | 包含影响数据的节点(空间数据除外)。 |
分层生成(Hierarchical Generation) | 包含负责控制分层生成模式的节点。 |
输入输出(Input Output) | 包含负责加载Alembic及其他外部数据的节点。 |
IO | 包含能控制与外部数据交互的节点。 |
元数据(Metadata) | 包含与属性交互的节点,无论是点上还是属性集上的属性。 |
参数(Param) | 包含能控制如何从Actor或蓝图变量检索参数的节点。 |
点运算(Point Ops) | 包含影响点以及点属性的节点。 |
取样器(Sampler) | 包含从空间数据源(例如体积、表面和网格体)生成点的节点。 |
空间(Spatial) | 包含能在数据之间创建空间关系、更改其内部空间数据或检索数据的节点。 |
生成器(Spawner) | 包含在给定点位置创建新数据或放置Actor的节点。 |
子图表(Subgraph) | 包含能处理子图表用法的节点。 |
你可以像使用蓝图那样添加注释(Comments)和重路由节点(Reroute Nodes),使图表更易于辨识。
图表编辑自定义
你可以使用图表设置(Graph Settings)面板中的一组专用属性来自定义PCG图表的编辑。
你可以使用这些属性自定义PCG图表的行为和工作流程,从而获得更符合预期的体验。 你还可以使用这些设置编译PCG图表模板,从而为项目定制PCG图表的工作流程。
节点过滤
你可以使用节点过滤(Node Filter)设置项按类别过滤节点选择。 过滤会基于包含或排除的原则进行。 要在选择上下文菜单中过滤节点,请启用按类别过滤节点(Filter Nodes by Category)属性,然后使用添加(+)按钮为已过滤类别(Filtered Categories)属性添加索引。 添加索引后,请在文本字段中输入类别名称,或使用下拉菜单选择节点类别。
更改过滤器即会更新节点控制板和上下文菜单中可用的选择项。
图表过滤
除过滤图表的可用节点外,你还可以过滤可用的子图表。 与节点过滤类似,首先启用过滤子图表(Filter Subgraph)属性,然后添加(+)一个新索引,并选择将在图表中可选的子图表。
属性和元数据
属性类似于变量,存储由其名称和类型定义的数据。 属性分为两类:
静态特性:固定且始终存在的特性。 这类特性以
$开头,如$Position。动态特性:在运行时创建的特性,并作为图表数据元数据的一部分存储。
元数据域
使用PCG图表中的特性时,必须考虑元数据所在的域。 域决定了你可以保存的信息类型,以及之后你可以如何使用并修改该信息。 针对所有元数据点,你都必须了解哪些域受支持,以及哪些域是默认域。 选择域时,域以@为前缀。
特性列表视图中有一个字段可以让你切换域。
你可以在使用PCG图表时使用三个域。 首先,针对为数据本身而设的特性,你可以使用数据(Data)域。 数据域仅限使用单个值,这意味着你不能像使用特性集那样存储多个值。 数据域的操作方式与其他域相同。 只要在特性前添加@Data前缀,就可以为其创建或添加特性,或使用元数据操作修改数据域。 例如,数据域中的特性 MyAttr 将变为@Data.MyAttr。 数据域是所有其他空间数据的默认域,当未指定任何域时,@Data域 在没有指定域时。
第二个域即"点(Points)"域,使用@Points前缀。
第三个域是"元素(Elements)"域,用于特性集,使用@Elements前缀。
属性选择器
某些PCG图标节点可以通过属性选择在静态和动态属性建提供互操作性。
属性选择器提供了一份属性列表,可以于所选的节点配合使用。 属性选择器使用以下命名规则:
以$开头的名称为静态特性,反之则是动态特性。
@Last表示被前一个节点操作过的最后一个动态特性。
例如,Math节点被用于在静态和动态属性上执行数学运算:
点击查看大图。
属性选择器的名称字段也被用于从组件中提取数据:
上图中的$Position.ZYX提供了$Position组件的反转。 下表列出了能够以这种方式操作的组件及其类型:
| 组件(Component) | 类型 |
|---|---|
向量(Vectors) | |
X、Y、Z、W、x、y、z、w | 双精度浮点。 不能与RGBA混合。 |
R、G、B、A、r、g、b、a | 双精度浮点。 不能与XYZW混合。 |
长度,尺寸(Length, Size) | 双精度浮点。 返回向量长度。 |
变换(Transforms) | |
位置,方位(Location, Position) | Vector3 |
缩放,缩放3D(Scale, Scale3D) | Vector3 |
旋转 | 四元数 |
旋转体(Rotators) | |
俯仰、偏航、滚转(Pitch, Yaw, Roll) | 双精度浮点 |
向前、向右、向上(Forward, Right, Up) | Vector3 |
四元数(Quaternions) | |
支持向量提取器(Support Vector extractor) | 向量 |
支持旋转器提取器(Support Rotator extractor) | 旋转器 |
C++设置重载
有些设置在C++属性元数据中被标记为PCG_Overridable。 对于蓝图节点,那些可见且实例可编辑的变量是可以被重载的。
被重载后,自动添加到节点的引脚属于高级引脚。 引脚分为两类:
全局重载:可接受任意数量的特性,并重载所有与设置名称完全匹配的特性的所有设置。
单独重载:可接受任意数量的特性,并在发现某个特性与设置名称完全匹配时(如只有一个特性,则无视名称)重载其指定设置。
属性类型必须匹配,但某些属性类型可以转换。
要了解确切的属性名称或类型,请查看重载引脚上的提示信息:
由于所有数据的域都是特定的,UPCGData的C++ API给出了一些函数,这些函数能识别受支持的域,并在FPCGMetadataDomainID(即用于指定元数据域的内部类)和FPCGAttributePropertySelector(即用于选择特性(Attributes)和属性(Properties)的公开类)之间来回转换。 所有FPCGMetadataDomain都有专属的一组特性和条目,且它们之间彼此独立。 访问器会使用FPCGAttributePropertySelector更新,以访问正确的域。
样条线元数据示例
以下各小节给出了实用的PCG元数据工作流程的示例配置。
样条线特性
你可以使用特性来直接修改控制点的属性。 使用添加(+) > 样条线(Spline) > 控制点(Control Points)即可访问下列特性属性。
| 名称 | 说明 | 类型 |
|---|---|---|
$Position | 控制点变换在世界参照系中的位置分量 | 向量 |
$Rotation | 控制点变换在世界参照系中的旋转分量 | 四元数/ 旋转器 |
$Scale | 控制点变换在世界参照系中的缩放分量 | 向量 |
$Transform | 控制点的世界变换 | 变换(Transform) |
$ArriveTangent | 在控制点处到达切线 | 向量 |
$LeaveTangent | 在控制点处离开切线 | 向量 |
$InterpType | 位置控制点的插值类型(与样条线控制点上设置的相同) | ESplinePointType |
$LocalPosition | 向量 | |
$LocalRotation | 控制点变换在样条线参照系中的旋转分量 | 四元数/ 旋转器 |
$LocalScale | 控制点变换在样条线参照系中的缩放分量 | 向量 |
$LocalTransfrom | 控制点的本地变换 | 变换(Transform) |
样条线数据
你也可以直接修改数据属性。 使用添加(+) > 样条线(Spline) > 全局(Global)即可访问下列数据属性。
| 名称 | 说明 | 类型 |
|---|---|---|
@Data.$SplineTransform | 样条线的变换 | FTransform |
@Data.$IsClosed | 样条线是否闭合(只读) | 布尔 |
样条线元数据
除控制点属性外,你还可以为样条线数据添加特性,并将其附加到控制点。 对样条线取样时,这些元数据将被插值。 此类元数据的行为与点或特性集元数据相同。
与点类似,你可以使用添加特性功能来创建新特性,或者使用元数据操作并指定要写入此特性的输出目标。
此外,控制点上的元数据是样条线元数据的默认项,但你也可以使用@ControlPoints来明确指定。
图表参数
与材质编辑器中的参数类似,PCG图表参数是由用户创建的可重载值,这有助于为各类情况创建可自定义的图表。 创建新参数的方法是:
打开PCG图标设置。
点击属性(Parameters)字段旁的 + 按钮。 这样即可创建新参数。
点击下拉箭头以转到新参数。 将其重命名并选择类型。
在PCG图表中修改参数值的方法如下:
你可以在图表参数中修改值,也可以在PCG资产的细节面板中修改值。
在PCG图表示例上修改参数值的方法如下:
在内容浏览器中打开资产,修改其值,或在PCG资产的细节面板中修改。
图表实例
PCG图表实例的工作原理类似于材质实例,利用图表参数帮助你以实例或PCG子图表的形式复用现偶的图表:
创建PCG图表实例的方法是:
选择关卡中的一个PCG资产。
在细节面板中选择PCG组件。
点击保存实例(Save Instance)按钮以新建一个实例。
为新图表实例命名并按下Enter键。
PCG组件
程序化节点图表可以通过PCG组件对你的关卡取样。 此组件可保存程序化节点图表的实例,并在编辑器中以及在运行时管理程序化内容的生成。 PCG组件添加为Actor的组件,或用作PCG体积的一部分,这是一种基本体积,适合用于快速设置程序化内容。
要将PCG图表连接到PCG组件,请执行下面的步骤:
在编辑器视口或大纲视图(Outliner)中,选择你想连接的PCG体积(PCG Volume)或蓝图类(Blueprint Class)。
在细节(Details)面板中,点击PCG组件(PCG Component)。
点击图表(Graph)下拉菜单,并选择你想使用的PCG节点图表。
点击生成(Generate)按钮以查看结果。
世界分区支持
将PCG资产分配到 世界分区 - 数据层 和 分层细节级别(HLOD)层 后, PCG图表会生成Actor并将其分配到同一数据层和同一HLOD层中。
如需详细了解如何将PCG用于世界分区,请参阅将PCG用于世界分区。
在PCG中调试
调试是PCG工作流程中的基本部分。
每个节点都有各种调试选项,可用于直观地显示PCG图表每个步骤中的点数据:
调试渲染
启用/禁用节点
检查
在节点的细节(Details)面板中选中调试(Debug)复选框或按D键,即可开关各节点的调试渲染。
在节点的细节(Details)面板中选中启用(Enabled)复选框或按E键,即可打开和关闭各个节点。
你还可以检查节点,以此在特性(Attributes)列表中显示某个节点所生成的所有点。
从调试树(Debug Tree)选择PCG组件。
右键点击要检查的节点。
选择检查(Inspect)。 你也可以按A键。
创建简单森林体积
程序化生成工具的常见用例是开放世界环境中的群系生成。
要创建基本森林群系生成器,请执行下面的步骤。
此示例使用的材质和静态网格体来自使用Fab下载的Megascans树木资产包:欧洲鹅耳枥集合。
创建关卡
在虚幻引擎中新建项目。
使用基本(Basic)关卡模板创建新关卡。 保存关卡。
删除地板(Floor)静态网格体,然后使用地形模式为关卡添加新地形。
使用塑造(Sculpt)工具为地形添加一些变化。
创建PCG体积
返回选择(Selection)模式并启用放置Actor(Place Actors)窗口(如果目前不可见)。
使用搜索类(Search Classes)框查找PCG体积(PCG Volume)并添加一个到你的关卡。
将PCG体积缩放为X=8.0, Y=8.0, Z=8.0
创建PCG图表资产
右键点击内容侧滑菜单(Content Drawer)或内容浏览器(Content Browser),找到创建的高级资产(Create Advanced Asset)> PCG,并选择PCG图表(PCG Graph)。
将新资产命名为PCG_ForestGen并按Enter键。
双击PCG_ForestGen打开PCG图表编辑器。
连接PCG组件
在编辑器视口或大纲视图(Outliner)中,选择PCG体积(PCG Volume)。
在细节(Details)面板中,点击PCG组件(PCG Component)。
点击图表(Graph)下拉菜单并从列表选择PCG_ForestGen。
创建点
在PCG图表编辑器窗口中,将Get Landscape Data节点添加到图表。
从Get Landscape Data节点的输出拖移并添加Surface Sampler节点。
选择Surface Sampler并按D键切换调试渲染。
返回编辑器窗口,选择PCG体积,然后点击细节面板中的生成(Generate)按钮。
现在你可以在编辑器视口中看到正在生成的点。 这些点符合地形的形状。
添加变化
在PCG图表编辑器中,选择Surface Sampler。
在细节面板中调整每平方米点数(Points Per Square Meter)、点范围(Points Extents)和松散度(Looseness)属性,从而添加更多点。
将每平方米点数(Points Per Square Meter)调整为0.15,从而将更多点添加到空间。
点范围(Points Extents)属性会控制各点的边界大小。 将X、Y和Z的值更改为50。
松散度属性将确定生成的点贴近网格形状的程度。 将松散度(Looseness)的值保留为1.0。
接下来,添加Transform Points节点。 此节点将向你的点添加定义范围内的额外移动、旋转和缩放变化。 将Surface Sampler节点的输出(Output)引脚连接到Transform Points节点的输入(Input)引脚。
在Surface Sampler节点上禁用调试渲染,并在Transform Points节点上启用它。
要添加一些旋转变化,请将最大旋转(Max Rotation)的Z值更改为360。 这样所有点都会获得0到360度之间的随机旋转。
PCG图表会生成点并将其旋转以符合地形的法线方向。 选中绝对旋转(Absolute Rotation)的复选框即可禁用此额外旋转。
要添加一些大小变化,请将X、Y和Z的缩放最小值(Scale Min)设置为0.5。 将X、Y和Z的缩放最大值(Scale Max)更改为1.2。
最终结果是有不少变化的一组点。
生成静态网格体
在PCG图表编辑器中,将Static Mesh Spawner节点添加到图表视口。 将Transform Points节点的输出(Output)引脚连接到Static Mesh Spawner的输入(Input)引脚。
选择Static Mesh Spawner。
在细节(Details)面板中,找到网格体条目(Mesh Entries)选项并点击+按钮,添加要生成的静态网格体。
点击网格体条目(Mesh Entries)旁边的下拉箭头以打开数组。
点击Index [0]旁边的下拉箭头。
点击描述符(Descriptor)旁边的下拉箭头。
点击静态网格体(Static Mesh)的下拉菜单并选择你想生成的树。 此示例使用SM_EuropeanHornbeam_Forest_01。
你可以将权重属性用于数组中的每个网格体条目,添加更多静态网格体并平衡多样性。 虚幻引擎添加了所有静态网格体条目的权重值,并将该数字除以每个单独的权重以确定每个条目生成的概率。