《InsideUE4》GamePlay架构学习
Level和World
前话
本次系列是关于知乎InsideUE系列的学习记录。原作链接如下:原文链接
Unity To UE
上一章谈到了Unity和UE里有了给各种各样的功能以及进行功能的对象。这一章谈谈两者是怎么将这些组织起来的。
首先,把所有物体同时放在一个世界可能会导致性能方面的问题,其次,玩家的活动范围是有限的,因此我们可以采取更细一点的粒度来规划这之间的关系。
在Unity中,存在一个 World(世界),它可能是3D的也可能是2D的,这是运行的基础。Unity将物体放在Scene(场景)中,这也就是不同的物体在不同的场景在同一世界下工作。我们可以通过SceneManager切换场景来实现不同功能,比如从开始UI界面场景跳到游戏主场景,不必要的物体通过切换场景来销毁释放,需要的物体保存下来,然后加载我们新场景需要的资源。
在UE中,对应Scene功能的就是Level(ULevel),而根据UE规则,Ulevel自然也是派生自UObject。
如图,Level带有一个ALevelScriptActor,这个组件允许我们在关卡里编写脚本,可以通过名字管理关卡中的所有Actor;另外也有一个继承自AInfo的AWorldSettings来记录本Level的各种规则属性,UE能直接访问这些数据。如下图:
如果这个Level的Settings是主PersistentLevel,它就是被当作整个World的WorldSettings。
World是一种Level的集合,提供一种Level动态加载的方法,但是在world加载的时候总是会有一个PersistentLevel来初始化世界的。
注意,Level里的Actors里也保存着AWorldSettings和ALevelScriptActor的指针,所以Actors实际上确实是保存了所有Actor。
有了Levels,我们把这些关卡放到World进行统一管理,一个World里有多个Level,我们可以设置这些Level在什么位置,是在一开始就加载进来,还是Streaming运行时加载。
UE里每个World支持一个PersistentLevel和多个其他Level:
Persistent的意思是一开始就加载进World,Streaming是后续动态加载的意思。Levels里保存有所有的当前已经加载的Level,StreamingLevels保存整个World的Levels配置列表。PersistentLevel和CurrentLevel只是个快速引用。在编辑器里编辑的时候,CurrentLevel可以指向其他Level,但运行时CurrentLevel只能是指向PersistentLevel。
思考
为什么AWorldSettings[0]的位置,而ALevelScriptActor不用?
void ULevel::SortActorList()
{
QUICK_SCOPE_CYCLE_COUNTER(STAT_Level_SortActorList);
if (Actors.Num() == 0)
{
// No need to sort an empty list
return;
}
LLM_REALLOC_SCOPE(Actors.GetData());
TArray<AActor*> NewActors;
TArray<