接上篇
老谭:UE4 LevelStreaming WorldComposition 源码分析:(一)场景加载机制zhuanlan.zhihu.com熟悉了场景加载的逻辑,接下来我们看看UE4里面最重要的两种流送方式:
- LevelStreamingVolume
- WorldComposition
这两种流送的入口都在UWorld 的Tick 函数里面:
LevelStreamingVolume
先从简单的LevelStreamingVolume开始。
LevelStreamVolume 一般是用于关卡型游戏的流送机制。比如玩家走到一个地方后,才加载接下来的场景,所以比较适合于有固定路线的关卡型游戏。先回顾一下这个怎么用的。
- 在场景中摆放
LevelStreamingVolume
。类似一个个的Trigger Collider,当玩家走进去的时候,就能触发对应场景的加载。 - 编辑准备一些SubLevel,在当前PersistentLevel的Levels 视图中配置好。
- 在SubLevel 的Level Details 视图中,关联好对应的Volume。
然后我们看下代码。StreamingVolume 的代码非常简单。整体来就几步:
- 遍历所有的PlayerController;
- 遍历相关的StreamingLevel;
- 遍历Level 相关的StreamingVolume;
- 如果当前PlayerController 在这个Volume 的范围内,则当前Level 需要被加载,否则相反;
- 遍历相关的StreamingLevel;
- 遍历相关的StreamingLevel;
- 设置Level 是否应被加载和可见;
// LevelTick.cpp
/**
* Issues level streaming load/unload requests based on whether
* players are inside/outside level streaming volumes.
*/
void UWorld::ProcessLevelStreamingVolumes(FVector* OverrideViewLocation)
{
// ...
if (bStreamingVolumesAreRelevant)
{
// Begin by assembling a list of kismet streaming objects that have non-EditorPreVisOnly volumes associated with them.
// @todo DB: Cache this, e.g. level startup.
TArray<ULevelStreaming*> LevelStreamingObjectsWithVolumes;
TSet<ULevelStreaming*> LevelStreamingObjectsWithVolumesOtherThanBlockingLoad;
for (ULevelStreaming* LevelStreamingObject : StreamingLevels)
{
if( LevelStreamingObject )
{
for (ALevelStreamingVolume* StreamingVolume : LevelStreamingObject->EditorStreamingVolumes)
{
if( StreamingVolume
&& !StreamingVolume->bEditorPreVisOnly
&& !StreamingVolume->bDisabled )
{
LevelStreamingObjectsWithVolumes.Add(LevelStreamingObject);
// ...
break;
}
}
}
}
// The set of levels with volumes whose volumes current contain player viewpoints.
TMap<ULevelStreaming*,FVisibleLevelStreamingSettings> VisibleLevelStreamingObjects;
// Iterate over all players and build a list of level streaming objects with
// volumes that contain player viewpoints.
for( FConstPlayerCont