目录
0 引言
在开发过程中,我以为
将Actor标记为可复制之后,有关这个Actor的所有属性都会进行一个同步。但其实只会同步一部分信息。
参考文章:Actor第一次被创建时经历了什么
官方参考文章:Actor复制流程详述
1 会同步的信息
1.1 对象的生命周期
Actor的生成和销毁会被自动同步,因为这些操作是通过Unreal Engine的网络复制系统处理的。服务器会将生成和销毁指令发送给所有客户端,以确保游戏状态的一致性。通过将Actor标记为可复制(bReplicates = true)
2 需要手动设置同步的信息
2.1 对象的基本属性(Location、Rotation、Scale)
Actor的移动状态同步需要设置 bReplicateMovement
变量为 true
时,才会网络同步给客户端。
C++属性:
蓝图属性:
在Actor内部是通过bReplicateMovement
变量和 FRepMovement
结构体配合实现控制 Actor 的运动状态的同步。以下是它们如何协同工作的总结:
2.1.1 bReplicateMovement
变量
- 作用:
bReplicateMovement
是AActor
类的一个布尔变量,用于控制是否自动复制 Actor 的运动状态。 - 设置:当
bReplicateMovement
被设置为true
时,Unreal Engine 会自动处理该 Actor 的运动状态的复制。 - 自动化:启用
bReplicateMovement
后,开发者无需手动编写复杂的复制逻辑,Unreal Engine 会自动同步位置、旋转、线性速度和角速度。
2.1.2 FRepMovement
结构体
- 作用:
FRepMovement
是一个结构体,包含了与 Actor 运动相关的多个属性,例如位置、旋转、线性速度和角速度。 - 存储和传输:当
bReplicateMovement
被启用时,Unreal Engine 内部会使用FRepMovement
结构体来存储和传输运动状态。 - 回调函数:可以使用
ReplicatedUsing
属性和回调函数(如OnRep_ReplicatedMovement
)来处理复制更新后的逻辑。
2.1.3 配合工作流程
-
启用复制:
- 在 Actor 的构造函数中,将
bReplicates
设置为true
,以启用网络复制。 - 将
bReplicateMovement
设置为true
,以启用运动状态的自动复制。
- 在 Actor 的构造函数中,将
-
自动处理:
- 当
bReplicateMovement
被设置为true
时,Unreal Engine 会自动使用FRepMovement
结构体来存储和传输运动状态。 - 服务器会将
FRepMovement
结构体中的数据(位置、旋转、线性速度和角速度)复制到客户端。
- 当
-
回调函数:
- 可以使用
ReplicatedUsing
属性和回调函数(如OnRep_ReplicatedMovement
)来处理复制更新后的逻辑。例如,当FRepMovement
结构体中的数据在客户端被更新时,回调函数会被调用,以便开发者可以在客户端上执行额外的逻辑。
- 可以使用
以下是一个简化的示例,展示了如何使用 bReplicateMovement
和 FRepMovement
来自动同步 Actor 的运动状态:
// MyActor.h
UCLASS()
class MYGAME_API AMyActor : public AActor
{
GENERATED_BODY()
public:
AMyActor();
protected:
virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
UPROPERTY(EditDefaultsOnly, ReplicatedUsing=OnRep_ReplicatedMovement, Category=Replication, AdvancedDisplay)
FRepMovement ReplicatedMovement;
UFUNCTION()
void OnRep_ReplicatedMovement();
};
// MyActor.cpp
AMyActor::AMyActor()
{
bReplicates = true; // 启用Actor的网络复制
bReplicateMovement = true; // 启用运动状态的自动复制
}
void AMyActor::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME(AMyActor, ReplicatedMovement);
}
void AMyActor::OnRep_ReplicatedMovement()
{
// 处理位置和速度的更新逻辑
if (RootComponent)
{
RootComponent->SetWorldLocationAndRotation(ReplicatedMovement.Location, ReplicatedMovement.Rotation);
// 其他更新逻辑,例如速度
}
}
2.1.4 UE4的特性
在 DS 上创建 一个Actor 后(可复制),然后重新设置Actor位置,发现客户端和服务器的位置都同步了,但是此时我并没有开启 bReplicateMovement 属性。然后在服务器 Tick 里面持续修改 Actor位置后发现客户端此时没有再同步。 (就是在服务器上创建一个可复制的 Actor 时,初始位置会自动同步到客户端。)
如果开启 bReplicateMovement 属性,服务器Tick里面修改Actor位置,客户端会持续同步位置。
总结:首次复制时会带上当前的 Location,这是在客户端打开通道(Open Channel)时写入的。在客户端打开通道之前对 Location 的修改会被包含在初始同步数据中,并在通道打开时发送给客户端。打开通道之后的修改则需要依赖于 bReplicateMovement 属性来决定是否同步。
2.2 组件的同步
如果我们在Actor中添加了某些组件,组件是否能网络同步,需要在组件内部设置,它并不会继承Actor同步的设置。
蓝图设置位置如下:
2.3 成员变量和方法
在类中声明的变量和方法如果需要进行网络同步,也需要再进行额外的设置才行。(使用UPROPERTY宏和元数据进行表示变量可复制)
2.4 Tags标签
在我的游戏开发过程中,我得知,Tags标签也是需要进行手动的同步设置的。只将Actor标记为可复制,并不会同步Tags信息 。