ReplicationGraph源码浅析

简介

UnrealEngine 基本的网络同步在进行同步时需要对每个连接判断每个 Actor 是否需要同步,开销较大;

可以通过实现 Replication ,实现一个不同的 ReplicationDriver 来优化性能;

ReplicationWorld 分为多个区域 Grid,把 Actor 根据所在 Grid 进行分类编组,可以快速找出需要同步的 Actor,同时确定哪些区域需要进行同步复制。

数据结构

classDiagram
    class UReplicationGraph
  1. FGlobalActorReplicationInfo :同步的 Actor 信息,包括

SettingsFClassReplicationInfo,每个 Actor Class 对应的同步配置,包括 CullDistanceReplicationPeriodFramePriorityScale 等;

EventsFGlobalActorReplicationEvents Events,记录休眠状态的改变时,从休眠列表中添加或者移除;

FConnectionReplicationActorInfo:对于 Connection 同步的 Actor 信息;

  1. ReplicationGraphNodeGraphNode 基类

  2. ReplicationGraphNode_ActorList:记录同步的 Actors;在 StreamingLevelCollection (以 SubLevelNameKeyList)中记录 SubLevelActor,否则在 ReplicationActorList 中记录。

  3. GlobalGraphNodes:维护 GridSpatialization2D

GraphNode

classDiagram
    class UReplicationGraphNode {
        TArray~UReplicationGraphNode*~ AllChildNodes
        GatherActorListsForConnection()
        RouteAddNetworkActorToNodes()
        RouteRemoveNetworkActorToNodes()
    }	

    UReplicationGraphNode <|-- UReplicationGraphNode_ActorList 
    class UReplicationGraphNode_ActorList {
    	FActorRepListRefView ReplicationActorList
    }
        
    UReplicationGraphNode <|-- UReplicationGraphNode_GridSpatialization2D
    class UReplicationGraphNode_GridSpatialization2D {
        TArray~TArray[UReplicationGraphNode_GridCell*]~ Grid;
    }
    
    UReplicationGraphNode <|-- UReplicationGraphNode_AlwaysRelevant
    class UReplicationGraphNode_AlwaysRelevant{
        TArray~UClass*~AlwaysRelevantClasses;
    }
    
    UReplicationGraphNode <|-- UReplicationGraphNode_ActorListFrequencyBuckets 
    
    UReplicationGraphNode_ActorList <|-- UReplicationGraphNode_GridCell
    
    UReplicationGraphNode_ActorList <|-- UReplicationGraphNode_AlwaysRelevant_ForConnection
  1. GridSpatalization2D:将世界划分为 2D 网格,按位置把 Actor 分到不同的 GridCell 中,按空间管理Actor 是否进行同步,每帧更新 GridCell 内的 Actor
  2. GridCellReplicationActorList 缓存着在该 GridCell 中的所有静态 ActorDynamicNodes 里记录动态的 ActorDormancyNode 里记录休眠的Actor
  3. AlwaysRelevant :处理总是发送 Net Updates 给 所有 ConnectionsActors
  4. AlwaysRelevant_ForConnection:处理总是发送 Net Updates 给 特定 ConnectionActors ,一般是同步给 PlayerControllerViewTarget
  5. ActorListFrequencyBuckets :记录地图格子上的 动态 Actor ;

生命周期

Init

graph TD

Start(UNetDriver::InitBase) --> A("UNetDriver::SetReplicationDriver")
A --> B("UReplicationGraph::InitializeActorsInWorld")
B --> | 将World中的同步对象添加到对应GraphNode | C("UReplicationGraph::InitializeForWorld")
C --> D("UReplicationGraph::AddNetworkActor(AActor* Actor)") 

A --> E(InitForNetDriver)
E --> F(InitGlobalActorClassSettings)
E --> G(InitGlobalGraphNodes)

InitGlobalActorClassSettings:设置 CulltDistanceReplicationPeriodFrame;注册 Actor 对应的 ClassReplicationInfoGlobalActorReplicationInfoMap

InitGlobalGraphNodes:创建 GridSpatialization2DAlwaysRelevantGraphNode

InitConnectionGraphNodes:创建 AlwaysRelevantForConnectionGraphNode

RouteAddNetworkActorToNodes :生成 Actor 时,添加 NetworkActor,分发 ActorGraphNode

RouteRemoveNetworkActorToNodes :销毁 Actor 时,删除 NetworkActor,通知GraphNode 移除 Actor

Repliate

graph TB
Start(ServerReplicateActors) --> A(PrepareForReplication)
A --> B(GatherActorListsForConnection)
B --> C(ReplicateActorListsForConnections_Default)
C --> D[ReplicateSingleActor]
  1. PrepareForReplication : 调用 GraphNodePrepareForReplication

    对于 GridSpatialization2D,会遍历 Actor,更新其所在的 Grid

    对于 AlwaysRelevant,记录需要同步给所有连接的 Actor

  2. GatherActorListsForConnection : 遍历 Connections 收集 ReplicationActorList

    针对每个 Connection 遍历 GlobalGraphNodesConnectionConnectionGraphNodes,调用其 GatherActorListsForConnection,收集需要同步给这个ConnectionActor

    对于 GridSpatialization2D,通过其 GridCellNode 根据 ActorViewLocation 收集;

    收集的 Actor 默认加到 GatheredReplicationListsForConnection 里的 EActorRepListTypeFlags.Default List

  3. ReplicateActorListsForConnections_Default:进行 Replicate 的同步检测与排序

    GatheredReplicationListsForConnection 里的 Actor,进行检测;

    首先排除 Dormancy、不满足ReplicateFrameActor,然后根据优先级排序(DistanceStarvation逻辑判定Owner & ViewTarget),将结果缓存在 PrioritizedReplicationList 中;

  4. ReplicateSingleActor:对排好序的 PrioritizedReplicationList 调用 ReplicateSingleActor 进行同步。

参考

UE ReplicationGraph Document