本质是WorldSubSystem中的一个:UWorldPartitionSubsystem
主要关注这个函数:
UWorldPartitionSubsystem::UpdateStreamingState
WorldPartitionSubsystem::Tick
主要是Editor下的部分Tick更新逻辑
WorldPartitionSubSystem::UpdateSteamingState
更新Streaming状态的单位是UWorldPartitionRuntimeCell
Cell的内部拥有一个UWorldPartitionLevelStreamingDynamic
继承自ULevelStreamingDynamic
所以某种程度上走了原来的Streaming的逻辑
储存这些Cell的容器是UWorldPartitionRuntimeHash
目前的实现是UWorldPartitionRuntimeSpatialHash
结构层次:
TArray<FSpatialHashStreamingGrid> UWorldPartitionRuntimeSpatialHash::StreamingGrids
TArray<FSpatialHashStreamingGridLevel> FSpatialHashStreamingGrid::GridLevels
TArray<FSpatialHashStreamingGridLayerCell> FSpatialHashStreamingGridLevel::LayerCells
TArray<TObjectPtr<UWorldPartitionRuntimeSpatialHashCell>> FPatialHashStreamingGridLayerCell::GridCells
然后会根据DataLayer又进行区分加载。
- 入口:
UWorld::InternalUpdateStreamingState()
UWorldPartitionSubsystem::UpdateStreamingState
获取当前世界WorldPartition并且UpdateStreamingPolicy->UpdateStreamingState();
有一层StreamingPolicy的抽象 实际上目前只有一种实现:UWorldPartitionStreamingPolicy::UpdateStreamingState
确定是否是BlockTillLevelStreamingComplete设置flag- 更新StreamingSource
UWorldPartitionStreamingPolicy::UpdateStreamingSources
获取PlayerController的位置创建FWorldPartitionStreamingSource
加入到StreamingSources 获得所有WorldPartition的StreamingSourceProviders
加入到StreamingSources 记录所有有效Source的更新速度,移除无效的Source
- 如果是客户端
UWorldPartitionRuntimeHash::GetStreamingCells
如果Source还是空的: 从DataLayerSubSystem里面取出所有AlwaysLoadedCells 否则 从DataLayerSubsystem里面取出所有需要激活的Cell以及需要加载的Cell
- 如果是服务端
- 激活所有的Cell
UWorldPartitionRuntimeHash::GetAllStreamingCells
遍历所有Cell全部返回(会筛选传入的DataLayer所属的Cell)
- 激活所有的Cell
UWorldPartitionStreamingPolicy::SetTargetStateForCells
EWorldPartitionRuntimeCellState::Unloaded:
UWorldPartitionRuntimeCell::UnLoad
遍历调用UWorldPartitionLevelStreamingDynamic::UnLoad
走传统Streaming的流程
EWorldPartitionRuntimeCellState::Loaded:
先进行优先级排序UWorldPartitionRuntimeHash::SortStreamingCellsByImportance
如果当前状态是Activated,则UWorldPartitionRuntimeCell::Deactive
LevelStreaming->Deactivate
走传统Streaming的流程
UWorldPartitionRuntimeCell::Load
LevelStreaming->Load
走传统Streaming的流程
EWorldPartitionRuntimeCellState::Activated:
先进行优先级排序UWorldPartitionRuntimeHash::SortStreamingCellsByImportance
如果LoadedCell中有该Cell则UWorldPartitionRuntimeCell::Activate
否则,如果不是AlwaysLoaded就加入ActivatedCelles中调用UWorldPartitionRuntimeCell::Activate
LevelStreaming->Activate
走传统Streaming的流程
UWorldPartitionRuntimeHas::``SortStreamingCellsByImportance
根据Cell内缓存的距离进行排序
UWorldPartitionRuntimeCell::SetStreamingPriority
ULevelStreaming::SetPriority
UWorld::UpdateStreamingLevelPriority
FStreamingLevelsToConsider::Reevaluate
UWorldPartitionStreamingPolicy::UpdateStreamingPerformance
如果当前是BlockTillLevelStreaming则returnUWorldPartitionRuntimeHash::GetStreamingPerformance
遍历需要Activate的Cell,获取Cell的Performance,获取最严重等级的性能LevelUWorldPartitionRuntimeCell::GetStreamingPerformanceForCell
靠 现在好像全部返回的Good 😓
- 更新StreamingSource
总结
综上所述WorldPartition本质上是一个WorldSubSystem,
并且通过Grid分层的方式动态管理了大量的子关卡(StreamingLevelDynamic)
然后最后还是走到StreamingLevel的逻辑里面。另一种方面说就是StreamingLevel的更上层包装