简单观察UE里Foliage吸附模型与地形的实现方式

目标

UE里,Foliage可以吸附所在的模型与地形:
在这里插入图片描述
在这里插入图片描述

本篇的目标是观察这个功能大概的实现方式。

0. Foliage的基础数据结构

首先,编辑器下的Foliage由每个关卡中的一个AInstancedFoliageActor来管理。

AInstancedFoliageActor有一个成员FoliageInfos

TMap<UFoliageType*, TUniqueObj<FFoliageInfo>> FoliageInfos;

FoliageInfos管理了每个FoliageType所对应的信息,以FFoliageInfo表示,而FFoliageInfo又包含了具体每个个体的信息:

// Editor-only placed instances
TArray<FFoliageInstance> Instances;

每个Foliage的个体都由一个FFoliageInstance表示

1. FoliageInstance的BaseComponent

FFoliageInstance有一个BaseComponent成员。
在这里插入图片描述
这个BaseComponent在放置的时候就被设置
在这里插入图片描述
再往前观察,可以看到它是通过Trace的方式找到一个instance所属的BaseComponent是什么。
在这里插入图片描述
如果是放在地形上,则Base就是一个LandscapeHeightfieldCollisionComponent
如果是放在模型上,则Base就是一个StaticMeshComponent

2. BaseComponent的保存方式方式

虽然FFoliageInstanceBaseComponent存储了每个植被个体的基底,但是经过观察,每次关卡重新打开后他的值都会变成Null。也就是说,它并未被序列化,即并未被保存。

经过观察,这一信息保存的方式如下:


一方面,对于AInstancedFoliageActor,它有一个InstanceBaseCache
在这里插入图片描述
通过它。可以知道对于一个FFoliageInstanceBaseId(也就是一个数字)对应的Component指针是什么。
在这里插入图片描述


另一方面,对于FFoliageInfo,有一个ComponentHash成员。
在这里插入图片描述
通过它可以知道,一个FFoliageInstanceBaseId对应了哪些个体。

扫描二维码关注公众号,回复: 15110508 查看本文章

以上两个数据都是被序列化的,即保存的。
而结合以上二者,就可以得到每个Foliage个体的BaseComponent是什么。

3. 当模型/地形改变时

可以在 InstancedFoliage.cpp 中的FFoliageStaticMesh::SetInstanceWorldTransform函数中加断点,即可断到模型/地形改变时,Foliage调整自身位置时的代码堆栈。


比如,当基底是模型。模型改变时为:
在这里插入图片描述
几个关键的部分为:

AActor::PostEditMove
UEngine::BroadcastOnActorMoved
AInstancedFoliageActor::OnLevelActorMoved
AInstancedFoliageActor::MoveInstancesForMovedComponent

主要的逻辑在AInstancedFoliageActor::MoveInstancesForMovedComponent
在这里插入图片描述
可以看到它通过 AInstancedFoliageActorInstanceBaseCacheFFoliageInfoComponentHash找到一个Component对应哪些个体。并且通过计算Transform偏差来改变Foliage的位置。


当地形改变时:
在这里插入图片描述
主要逻辑在ULandscapeHeightfieldCollisionComponent::SnapFoliageInstances中:

在这里插入图片描述
可以看到它也是通过 AInstancedFoliageActorInstanceBaseCacheFFoliageInfoComponentHash找到一个Component对应哪些个体。而Foliage的位置改变则是通过在个体的位置上使用Trace的方式。

总结

Foliage吸附模型与地形的实现方式是:

在放置Foliage个体的时候,通过Trace的方式找到其基底是什么,写到BaseComponent中。随后, AInstancedFoliageActorInstanceBaseCacheFFoliageInfoComponentHash会保存这一信息,后续也是通过他们找到个体对应基底的信息的。

当模型改变时,AInstancedFoliageActor::MoveInstancesForMovedComponent会被调用,它计算模型Transform的改变偏差,并使用这个偏差设置Foliage的新位置。

当地形改变时,ULandscapeHeightfieldCollisionComponent::SnapFoliageInstances会被调用。它使用Trace得到地形高度,并通过它设置Foliage的新位置。

猜你喜欢

转载自blog.csdn.net/u013412391/article/details/129777708
今日推荐