本质是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::SetTargetStateForCellsEWorldPartitionRuntimeCellState::Unloaded:UWorldPartitionRuntimeCell::UnLoad遍历调用UWorldPartitionLevelStreamingDynamic::UnLoad走传统Streaming的流程
EWorldPartitionRuntimeCellState::Loaded:先进行优先级排序UWorldPartitionRuntimeHash::SortStreamingCellsByImportance如果当前状态是Activated,则UWorldPartitionRuntimeCell::DeactiveLevelStreaming->Deactivate走传统Streaming的流程
UWorldPartitionRuntimeCell::LoadLevelStreaming->Load走传统Streaming的流程
EWorldPartitionRuntimeCellState::Activated:先进行优先级排序UWorldPartitionRuntimeHash::SortStreamingCellsByImportance如果LoadedCell中有该Cell则UWorldPartitionRuntimeCell::Activate否则,如果不是AlwaysLoaded就加入ActivatedCelles中调用UWorldPartitionRuntimeCell::ActivateLevelStreaming->Activate走传统Streaming的流程
UWorldPartitionRuntimeHas::``SortStreamingCellsByImportance根据Cell内缓存的距离进行排序
UWorldPartitionRuntimeCell::SetStreamingPriorityULevelStreaming::SetPriorityUWorld::UpdateStreamingLevelPriorityFStreamingLevelsToConsider::Reevaluate
UWorldPartitionStreamingPolicy::UpdateStreamingPerformance如果当前是BlockTillLevelStreaming则returnUWorldPartitionRuntimeHash::GetStreamingPerformance遍历需要Activate的Cell,获取Cell的Performance,获取最严重等级的性能LevelUWorldPartitionRuntimeCell::GetStreamingPerformanceForCell靠 现在好像全部返回的Good 😓
- 更新StreamingSource
总结
综上所述WorldPartition本质上是一个WorldSubSystem,
并且通过Grid分层的方式动态管理了大量的子关卡(StreamingLevelDynamic)
然后最后还是走到StreamingLevel的逻辑里面。另一种方面说就是StreamingLevel的更上层包装
