Language:
Page Info
Engine Version:
Share
此中文页面内容对应的英文页面有后续更新,如需浏览最新文档可切换至英文页面浏览。

Actor 复制流程详述

大多数 actor 复制操作都发生在 UNetDriver::ServerReplicateActors 内。在这里,服务器将收集所有被认定与各个客户端相关的 actor,并发送那些自上次(已连接的)客户端更新后出现变化的所有属性。

这里还定义了一个专门流程,指定了 actor 的更新方式、要调用的特定框架回调,以及在此过程中使用的特定属性。其中最重要的包括:

  • AActor::NetUpdateFrequency - 用于确定 actor 的复制频度

  • AActor::PreReplication - 在复制发生前调用

  • AActor::bOnlyRelevantToOwner - 如果此 actor 仅复制到所有者,则值为 true

  • AActor::IsRelevancyOwnerFor - 用于确定 bOnlyRelevantToOwner 为 true 时的相关性

  • AActor::IsNetRelevantFor - 用于确定 bOnlyRelevantToOwner 为 false 时的相关性

相应的高级流程如下:

  • 循环每一个主动复制的 actor(AActor::SetReplicates( true )

    • 确定这个 actor 是否在一开始出现休眠(DORM_Initial),如果是这样,则立即跳过。

    • 通过检查 NetUpdateFrequency 的值来确定 actor 是否需要更新,如果不需要就跳过

    • 如果 AActor::bOnlyRelevantToOwner 为 true,则检查此 actor 的所属连接以寻找相关性(对所属连接的观察者调用 AActor::IsRelevancyOwnerFor)。如果相关,则添加到此连接的已有相关列表。

      • 此时,这个 actor 只会发送到单个连接。

    • 对于任何通过这些初始检查的 actor,都将调用 AActor::PreReplication

      • PreReplication 可以让您决定是否针对连接来复制属性。这时要使用 DOREPLIFETIME_ACTIVE_OVERRIDE

    • 如果同过了以上步骤,则添加到所考虑的列表

  • 对于每个连接:

    • 对于每个所考虑的上述 actor

      • 确定是否休眠

      • 是否还没有通道

        • 确定客户端是否加载了 actor 所处的场景

          • 如未加载则跳过

        • 针对连接调用 AActor::IsNetRelevantFor,以确定 actor 是否相关

          • 如不相关则跳过

    • 在归连接所有的相关列表上添加上述任意 actor

    • 这时,我们拥有了一个针对此连接的相关 actor 列表

    • 按照优先级对 actor 排序

    • 对于每个排序的 actor:

      • 如果连接没有加载此 actor 所在的关卡,则关闭通道(如存在)并继续

      • 每 1 秒钟调用一次 AActor::IsNetRelevantFor,确定 actor 是否与连接相关

      • 如果不相关的时间达到 5 秒钟,则关闭通道

      • 如果相关且没有通道打开,则立即打开一个通道

      • 如果此连接出现饱和

        • 对于剩下的 actor

          • 如果保持相关的时间不到 1 秒,则强制在下一时钟单位进行更新

          • 如果保持相关的时间超过 1 秒,则调用 AActor::IsNetRelevantFor 以确定是否应当在下一时钟单位更新

      • 对于通过了以上这几点的 actor,将调用 UChannel::ReplicateActor 将其复制到连接

将 Actor 复制到连接

UChannel::ReplicateActor 将负责把 actor 及其所有组件复制到连接中。其大致流程如下:

  • 确定这是不是此 actor 通道打开后的第一次更新

    • 如果是,则将所需的特定信息(初始方位、旋转等)序列化

  • 确定该连接是否拥有这个 actor

    • 如果没有,而且这个 actor 的角色是 ROLE_AutonomousProxy,则降级为 ROLE_SimulatedProxy

  • 复制这个 actor 中已更改的属性

  • 复制每个组件中已更改的属性

  • 对于已经删除的组件,发送专门的删除命令