文章目录
- 前言
- 一、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的Cell
if (WorldPartition->IsInitialized())
{
WorldPartition->RuntimeHash->GetStreamingCells(StreamingSources, FrameActivateCells, FrameLoadCells);
}
}
else
{
//后端对SteamingCells的处理,这里会处理归属DataLayer的Cell
const 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
{
//先拿到当前世界所有的DataLayers
const 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的Cell
for (const FSpatialHashStreamingGrid& StreamingGrid : StreamingGrids)
{
if (!StreamingGrid.bClientOnlyVisible || bShouldConsiderClientOnlyVisible)
{
/*这里会根据StreamingSource设置的形状(这个可以在组件中设置Shapes,默认情况是用以StreamingSource作为圆心,以Grid的LoadingRange作为半径构成圆)来判断是否与Cell相交,具体逻辑:
1.首先根据传入的Coords,获取该坐标出的Cell,并GetBuounds
2.判断是否相交,具体逻辑在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 …