文章目录
- 前言
- 一、Data Layers的使用
- 1.添加Actor到Data Layers
- 2.运行时处理
- 总结
上一篇:虚幻引擎(UE5)-大世界分区WorldPartition教程(三)
前言
Data Layers(UE4中叫Layers)用于将Actor划分到不同的Layer中,通过在编辑器和运行时激活和停用某些数据层,有条件地加载世界数据来组织大世界,前面提到的划分Cell是对WP关卡的横向划分,DataLayer是对WP关卡的纵向划分
该系统提供了一种对资源进行分组管理的方式,比如可以将建筑放到一个Layer中,将植被放到另一个Layer中,并且在编辑和Gameplay层都可以操作这个Layer,这不但方便了编辑管理世界,而且开发人员也可以在Gameplay层做一些比较有趣的玩法,比如白天和黑夜系统,荒野和城市互换等
提示:以下是本篇文章正文内容
一、Data Layers的使用
1.添加Actor到Data Layers
再上方工具栏中找到 Window->World Partition->Data Layers Outliner,然后在Data Layers Outliner中右键创建新的DataLayer
新建DataLayer后在面板中的数据层资产中 创建数据层:
然后在Actor的Details面板中为Actor指定Data Layers:
这里需要注意的是,Data Layers只有在编辑WP关卡时才生效,如果是普通关卡,需要像UE4那样在Layers中添加
这个时候返回数据层面板中就可以根据策略去加载了,可以控制初始显示和隐藏等等,也能通过蓝图去控制显示方式。
2.运行时处理
Data Layers数据是由UDataLayerSubsystem负责管理的,具体处理如下:
前后端分开:
void UWorldPartitionStreamingPolicy::UpdateStreamingState()
{//前后端对Cells处理的逻辑分开if (NetMode == NM_Standalone || NetMode == NM_Client || AWorldPartitionReplay::IsEnabled(World)){ //前端对StreamingCells的处理,GetStreamingCells会处理DataLayer的Cellif (WorldPartition->IsInitialized()){WorldPartition->RuntimeHash->GetStreamingCells(StreamingSources, FrameActivateCells, FrameLoadCells);}}else{//后端对SteamingCells的处理,这里会处理归属DataLayer的Cellconst UDataLayerSubsystem* DataLayerSubsystem = WorldPartition->GetWorld()->GetSubsystem<UDataLayerSubsystem>();//处理不属于DataLayer的Cells和以及归属于状态为Activate的DataLayer里的Cells,放入ActivateStreamingCells中WorldPartition->RuntimeHash->GetAllStreamingCells(ActivateStreamingCells, /*bAllDataLayers=*/ false, /*bDataLayersOnly=*/ false, DataLayerSubsystem->GetEffectiveActiveDataLayerNames());//只处理DataLayer中的Cells,并放入LoadStreamingCells中if (DataLayerSubsystem->GetEffectiveLoadedDataLayerNames().Num()){WorldPartition->RuntimeHash->GetAllStreamingCells(LoadStreamingCells, /*bAllDataLayers=*/ false, /*bDataLayersOnly=*/ true, DataLayerSubsystem->GetEffectiveLoadedDataLayerNames());}}
}
前台处理部分:
bool UWorldPartitionRuntimeSpatialHash::GetStreamingCells(const TArray<FWorldPartitionStreamingSource>& Sources, UWorldPartitionRuntimeHash::FStreamingSourceCells& OutActivateCells, UWorldPartitionRuntimeHash::FStreamingSourceCells& OutLoadCells) const
{//先拿到当前世界所有的DataLayersconst UDataLayerSubsystem* DataLayerSubsystem = GetWorld()->GetSubsystem<UDataLayerSubsystem>();//如果没有StreamingSource的话,处理所有的StreamingGrid中的AlwaysLoaded Cells,if (Sources.Num() == 0){for (const FSpatialHashStreamingGrid& StreamingGrid : StreamingGrids){if (!StreamingGrid.bClientOnlyVisible || bShouldConsiderClientOnlyVisible){/*这里处理了归属于DataLayerSubsystem的Cell,具体处理逻辑:1.如果不归属于DataLayer且被设置为IsAlwaysLoaded的Cell和归属于DataLayer且它被设置Activated的Cell被放入OutActivateCells中2.如果归属于DataLayer且它被设置Loaded的Cell被放入OutLoadCells中*/StreamingGrid.GetAlwaysLoadedCells(DataLayerSubsystem, OutActivateCells.GetCells(), OutLoadCells.GetCells());}}}else{//获取所有基于StreamingSource的Cellfor (const FSpatialHashStreamingGrid& StreamingGrid : StreamingGrids){if (!StreamingGrid.bClientOnlyVisible || bShouldConsiderClientOnlyVisible){/*这里会根据StreamingSource设置的形状(这个可以在组件中设置Shapes,默认情况是用以StreamingSource作为圆心,以Grid的LoadingRange作为半径构成圆)来判断是否与Cell相交,具体逻辑:1.首先根据传入的Coords,获取该坐标出的Cell,并GetBuounds2.判断是否相交,具体逻辑在FSquare2DGridHelper::FGrid2D::ForEachIntersectingCells中,这里会涉及到Cell的划分3.如果不归属于DataLayer且被设置为IsAlwaysLoaded的Cell和归属于DataLayer且它被设置Activated的Cell被放入OutActivateCells中4.如果归属于DataLayer且它被设置Loaded的Cell被放入OutLoadCells中5.调用GetAlwaysLoadedCells方法,如前所述,不累述*/StreamingGrid.GetCells(Sources, DataLayerSubsystem, OutActivateCells, OutLoadCells);}}}
}
如果是要在Gameplay中使用DataLayer的话调用UDataLayerSubsystem::SetDataLayerRuntimeState方法即可,大家可以自己尝试一下
总结
其中总的来说Data Layers实际上就是UE4中的Layers系统的Puls版,它可以方便的实现同个世界的不同变体,不仅方便编制者管理复杂的世界,同时也能在Gameplay中实现有趣的玩法以上就是今天要讲的内容
到此虚幻引擎(UE5)-大世界分区WorldPartition教程暂时完结了 To be Continued …