文章目录

  • 前导文章
  • 关卡概要
  • PCGGraph
  • Points From Actor Tag作为PCG的分割工具
  • 分层装饰
  • 一些知识点和技巧
  • 使用Attribute Operation将属性暂存到临时属性中
  • 是否生成碰撞
  • 小结


在上述博文中,我们了解了《Electric Dreams》项目的宏观工作流以及构建关卡的基本思路,再来看这个“PCGDemo_Ditch”关卡就很好理解了。

文件位置:/Content/Levels/PCG/Breakdown_Levels/ElectricDreams_PCGDitchAssembly.umap

“PCGDemo_Ditch”关卡主要为我们展示了PCG的小技巧:

  • 使用自定义节点Points From Actor Tag作为PCG的分割工具
  • 分层装饰的思想

关卡概要

UE5 源码编译 check dependencies ue5demo_常用方法

PCGGraph

UE5 源码编译 check dependencies ue5demo_ue5_02

Points From Actor Tag作为PCG的分割工具

在 PCGDemo_Ditch关卡中使用了很多Points From Actor Tag,这是一个很好用的自定义节点,可以直接移植到我们自己的项目中,下面我们来看一下它的主要逻辑,Points From Actor Tag的核心就在于Excute with Context中的如下部分:

UE5 源码编译 check dependencies ue5demo_数据库_03

从整个场景中获取到所有携带指定Tag的Actor,然后用它们的Transform以及Scaled Bounds组成Point Cloud输出。我们再看一下GetActorBoundsPCG的具体逻辑:

GetActorBoundsPCG

FBox UPCGBlueprintHelpers::GetActorBoundsPCG(AActor* InActor, bool bIgnorePCGCreatedComponents)
{
	return PCGHelpers::GetActorBounds(InActor, bIgnorePCGCreatedComponents);
}

以及它调用的GetActorBounds

FBox GetActorBounds(const AActor* InActor, bool bIgnorePCGCreatedComponents)
	{
		// Specialized version of GetComponentsBoundingBox that skips over PCG generated components
		// This is to ensure stable bounds and no timing issues (cleared ISMs, etc.)
		FBox Box(EForceInit::ForceInit);

		const bool bNonColliding = true;
		const bool bIncludeFromChildActors = true;

		if (InActor)
		{
			InActor->ForEachComponent<UPrimitiveComponent>(bIncludeFromChildActors, [bNonColliding, bIgnorePCGCreatedComponents, &Box](const UPrimitiveComponent* InPrimComp)
			{
				// Note: we omit the IsRegistered check here (e.g. InPrimComp->IsRegistered() )
				// since this can be called in a scope where the components are temporarily unregistered
				if ((bNonColliding || InPrimComp->IsCollisionEnabled()) &&
					(!bIgnorePCGCreatedComponents || !InPrimComp->ComponentTags.Contains(DefaultPCGTag)))
				{
					Box += InPrimComp->Bounds.GetBox();
				}
			});
		}
		else
		{
			UE_LOG(LogPCG, Error, TEXT("Actor is invalid in GetActorBounds"));
		}

		return Box;
	}

从上述代码可以看到,最关键的就是获取ActorUPrimitiveComponent组件的BoundsBox,并且可以每个Actor可以携带多个Volume。

这个节点的常用方法是在关卡中设定一些Volume并添加相应Tag,然后在PCG中通过Tag筛选出这些Volume,并排除它们体积。

UE5 源码编译 check dependencies ue5demo_数据库_04

下图中有一个使用环形Spline生成的Ditch,然后使用几个标记有"PCG_EXCLUDE"标签的Volume(各种Volume都可以)为它开了两个口子。

UE5 源码编译 check dependencies ue5demo_ue5_05


在"ElectricDreams_Env"可以也找到应用范例:

UE5 源码编译 check dependencies ue5demo_自定义_06

分层装饰

UE5 源码编译 check dependencies ue5demo_ue5_02


分层装饰是构建PCG的一个重要的思想, PCGDemo_Ditch关卡中,一个Ditch由如下4个从主到次的部分组成:

  1. Ditch的主体
  2. 树木和石头
  3. Ditch和地面的连接部
  4. UE5 源码编译 check dependencies ue5demo_技术解析_08

  5. 污渍细节

UE5 源码编译 check dependencies ue5demo_ue5_09


本关卡中分层构建PCG的逻辑虽然比较复杂,但并不难理解,本文中就不展开解释了。

一些知识点和技巧

使用Attribute Operation将属性暂存到临时属性中

UE5 源码编译 check dependencies ue5demo_自定义_10

是否生成碰撞

UE5 源码编译 check dependencies ue5demo_ue5_11

小结

PCG真好玩啊,时间的关系,本文先写到这里,如果有错误敬请指正!