Language:
Page Info
Engine Version:
Share

属性复制

每个Actor维护一个属性列表,这些属性可以标记为复制到客户端。每当服务器端变量的值发生更改时,服务器就会向客户端发送更新后的值。变量可能在客户端发生了更改,在这种情况下,新值将覆盖旧值。属性更新仅来自服务器(即客户端永远不会向服务器发送属性更新)。

默认情况下会复制某些属性(例如,位置、旋转、所有者等)。这些属性是框架通常为实现基本多人游戏所依赖的属性。在那里,您可以根据需要标记要复制的其他属性。

Actor属性复制可靠。这意味着,Actor的客户端版本的属性最终将反映服务器上的值,但是可能会跳过一些个别的属性值更改。

设置要复制的属性

要复制属性,您需要做几件事情: 在定义属性的Actor类标头处,您需要确保将“replicated”关键字作为UPROPERTY声明的参数之一:

class ENGINE_API AActor : public UObject
{
    UPROPERTY( replicated )
    AActor * Owner;
};

在Actor类的实现过程中,需要实现GetLifetimeReplicatedProps函数:

void AActor::GetLifetimeReplicatedProps( TArray< FLifetimeProperty > & OutLifetimeProps ) const
{
    DOREPLIFETIME( AActor, Owner );
}

在Actor的构造函数中,确保将bReplicates标记设置为true:

AActor::AActor( const class FPostConstructInitializeProperties & PCIP ) : Super( PCIP )
{ 
    bReplicates = true;
}

对于当前实例化的Actor类型的每个副本,成员变量“Owner”现在将同步到所有连接的客户端(在本例中为基础Actor类)。

网络更新优化

数据驱动型网络更新频率

Actor将观察在其“NetUpdateFrequency”变量中设置的最大更新频率。通过在不太重要或不太频繁变化的Actor上降低该变量,网络更新可以变得更高效,同时在有限带宽的场景中可能会带来更流畅的游戏体验。常见的更新频率值为:对于重要且不可预知的Actor,例如在射击游戏中由玩家控制的角色,为10(每0.1秒更新一次);对于行动缓慢的角色,例如在合作类游戏中由AI控制的怪物,为5(每0.2秒更新一次),对于游戏进程不是很重要但仍通过网络同步的以及/或者由服务器端逻辑控制因而需要复制的后台Actor,为2(每0.5秒更新一次)。

自适应型网络更新频率

通过自适应型网络更新频率,我们可以节省CPU周期,这些CPU周期通常会在没有任何实际更改的情况下多次尝试复制Actor而浪费掉。当启用了该功能时,系统将根据各个Actor的更新是否有意义,动态调整其更新频率。在该上下文中,“有意义的”更新为初始化了Actor、添加或删除了子对象(即拥有的组件)、或者更改了Actor上或其任何子对象上复制字段值的任何更新。每个Actor可能的更新速率范围由Actor本身的两个变量决定:“NetUpdateFrequency”和“MinNetUpdateFrequency”。“NetUpdateFrequency”表示Actor每秒尝试更新自己的最大次数,而“MinNetUpdateFrequency”表示每秒尝试更新的最小次数。使用该功能可以大大提高复制性能。

(高级)更新频率降低算法

在更新尝试期间,Actor将确定最近一次有意义的更新发送到现在有多长时间,如果它们发送了有意义的更新,将记录新的时间。如果考虑进行更新的Actor超过2秒没有发送有意义的更新,那么它将开始降低更新频率,在没有发送有意义的更新的情况下,更新频率将在7秒后达到最小。例如,如果更新延迟在0.1秒到0.6秒之间的Actor在3秒内没有任何有意义的更新,那么它将在0.2秒内尝试下一次更新。

(高级)更新频率增加算法

在发送一个有意义的更新之后,Actor将安排下一个更新发生的时间,使其比前两次有意义的更新之间的时间短30%,并且处于最小更新频率与最大更新频率之间。例如,如果Actor在两次有意义的更新之间恰好间隔了一秒,那么它会将下一次更新尝试安排在未来0.7秒(或者接近指定的最小与最大更新频率的时间)。对于接下来每次有意义的更新,都将重复该计算,如果Actor开始频繁地进行数据或子对象更改,将快速缩短更新之间的时间。