总览
Mass 联网的核心思路是:服务器维护权威实体,但客户端只需要知道与自己相关的一小部分实体。MassReplication 用 Client Bubble 组织每个客户端的相关实体集合,再用 FastArray 风格的数据同步必要状态。它不是把每个 Mass 实体都变成 replicated Actor,而是把 Mass 数据压缩成面向客户端的复制项。
这对于城市人群、交通、战场单位都很重要。玩家附近的路人需要比较准确的位置和表现;远处只需要低频或根本不需要;不可见实体仍可在服务器模拟。
源码依据
MassReplicationFragments.h 定义 FMassNetworkIDFragment、FMassReplicatedAgentFragment、FMassReplicationViewerInfoFragment、FMassReplicationLODFragment、FMassReplicationParameters、FMassReplicationSharedFragment、FMassReplicationGridCellLocationFragment 和 FMassInReplicationGridTag。FMassReplicationParameters 包含 LODDistance、LODMaxCount、LODMaxCountPerViewer、UpdateInterval、BubbleInfoClass 和 ReplicatorClass。MassClientBubbleHandler.h 中 TClientBubbleHandlerBase 负责添加、移除、标脏、客户端 PostReplicatedAdd/Change/Remove 等流程。
架构分析
Client Bubble 是“每个客户端看到的 Mass 世界切片”。服务器按 viewer 距离、LOD、数量上限和网格查找,把实体加入某客户端的 Bubble。Bubble Handler 管理网络 ID、Agent Handle、FastArray Item 和实体映射。客户端收到新增项后,可以创建对应 Mass Entity 或更新已有实体的数据。
联网设计要先回答三个问题:哪些数据需要服务器权威,哪些数据客户端可插值,哪些实体不需要同步。比如路人的精确心情、内部 StateTree 状态不一定要同步;位置、朝向、表现类型、动作状态可能需要。能不同步的不要同步,能低频的不要高频。
使用案例
一个路人复制数据可以这样拆:
USTRUCT()
struct FReplicatedCrowdAgent
{
GENERATED_BODY()
UPROPERTY()
FMassNetworkID NetID;
UPROPERTY()
FVector_NetQuantize10 Location;
UPROPERTY()
FRotator Rotation;
UPROPERTY()
uint8 VisualState = 0;
};
服务器 Replicator 从 Mass Fragment 采样数据,写入 FastArray Item;客户端 Bubble Handler 在新增实体时用 Config Template 生成本地 Mass Entity,再把复制数据写入 Transform、Representation 或自定义 Fragment。远处实体可以只同步 Location 和 VisualState,近处才同步更细的动画状态。
项目落地
先只同步 Transform 和一个 VisualState,验证客户端出现、移动、离开 Bubble、重进 Bubble 都正确。第二步加入 LOD 更新间隔和数量上限。第三步才同步行为表现,例如挥手、排队、使用设施。最后再考虑客户端预测或插值。Mass 复制问题通常不是单个包错,而是 Bubble 进出、NetID 复用、实体销毁和表示切换的边界条件。
常见坑
不要把每个实体都转换成 replicated Actor。不要同步大型 Fragment 或内部状态机全部数据。不要忽略 LODMaxCountPerViewer,多人同屏时每个客户端的预算不同。不要忘记处理删除乱序,源码里有 AgentRemoveInterval 相关逻辑就是为了解决 add/remove 时序。不要让客户端本地生成的表现和服务器同步数据互相覆盖。
源码路径索引
MassReplication/Public/MassReplicationFragments.hMassReplication/Public/MassClientBubbleHandler.hMassReplication/Public/MassReplicationProcessor.hMassReplication/Public/MassReplicationTrait.h