虚幻引擎(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:

这个时候返回数据层面板中就可以根据策略去加载了,可以控制初始显示和隐藏等等,也能通过蓝图去控制显示方式。

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中实现有趣的玩法以上就是今天要讲的内容

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值