跳至主要內容

NT-2.0|Actor复制

Mr.Si大约 8 分钟unreal

问题

头像
角色类中添加了如下函数:按数字1可以Spawn生成Actor
头像
进行简单网络同步测试。同时客户端和服务端后,客户端按1生成Actor,服务端并没有同步
头像
但是,在服务端按1时,客户端却同步了!
头像
我明明已经启用了网络复制!为什么客户端中按1,服务端没有同步生成?
头像
先搞懂几个概念

Replication|复制

复制是服务器将信息/数据传递给客户端的行为。

中文
中文
英文
英文

对应的CPP

AMyCharacter::ATestCharacter(const FObjectInitializer& ObjectInitializer)
    : Super(ObjectInitializer)
{
    bReplicates = true;
}
头像
在UE中继承自Actor的派生都有Replication(包括组件)
头像
先不讨论SpawnActor的情况,在场景中置入测试Actor,并关闭复制。
头像
关闭复制。
头像
运行后,两端都能正常显示,这个复制可有可无?
头像
并不是,虽然两端都看到了这个Actor,他们彼此独立。
头像

若将客户端上的网络加载关闭,原形毕露。

头像
此时虽不可见,生成处依然会有球体的碰撞。
GIF
头像
啊?我怎么越听越迷糊了?为什么关闭了网络加载依然会有碰撞?
头像
别急,咱再补几个概念。

网络权威

Authority|Remote

罗马音读音为 /əˈθɔːrəti/(英式发音)或 /əˈθɒrəti/(美式发音)。

头像
客户端确实生成了Actor,但我们认为所有客户端不可信,即服务器拥有绝对权限(Authority)。
头像

在UE,可以通过调用 HasAuthority() 来检查当前代码是否在具有 "Authority" 的实体上执行。例如:

if (HasAuthority())
{
    // 在具有Authority的实体上执行的代码
}
BP宏
BP宏
展开
展开
头像
翻看翻看源码,一探究竟。

ENetRole|Remote

头像
可以看到实际它调用了GetLocalRole()
GetLocalRole() == ROLE_Authority
原文
/** The network role of an actor on a local/remote network context */
UENUM()
enum ENetRole : int
{
	/** No role at all. */
	ROLE_None,
	/** Locally simulated proxy of this actor. */
	ROLE_SimulatedProxy,
	/** Locally autonomous proxy of this actor. */
	ROLE_AutonomousProxy,
	/** Authoritative control over the actor. */
	ROLE_Authority,
	ROLE_MAX,
};
头像
蓝图中节点如下:
头像
可以看到客户端的角色只有Remote权限没有Authority。

Character继承Pawn,Pawn继承Actor,本质还是Actor所以可以调到。

GIF
头像
便于测试,咱把代码写在Actor的tick中,然后Debug每个场景中的的网络权限。
GIF
头像
客户端并没有网络权限,只是个无情的模拟机器。
头像
既然用不用Replication都能正确显示,那么这个Replication到底有什么用?
头像
场景默认生成的Actor确实看不出太多区别,但你提到的SpawnActor就看出大区别了。
头像

将复制关闭后,在服务端,也只能在本地生成,无法同步。即便是开启客户端上的网络加载依然如此。

头像

可以理解成一开始这个Level中压根就没有这个对象是吧,也就不存在客户端上的网络加载行为了。

网络模型

头像
在多人在线游戏中,客户端通常是模仿服务器行为的,因为服务器负责游戏世界的状态和逻辑。这种架构被称为客户端-服务器模型。
头像
突然官腔!

基本网络模式

网络模式说明
独立 (Standalone)游戏作为服务器运行,不接受远程客户端连接。参与游戏的玩家必须为本地玩家。此模式用于单人游戏和本地多人游戏。其将运行本地玩家适用的服务器逻辑和客户端逻辑。
客户端 (Client)游戏作为网络多人游戏会话中与服务器连接的客户端运行。其不会运行服务器逻辑。
聆听服务器 (Listen Server)游戏作为主持网络多人游戏会话的服务器运行。其接受远程客户端中的连接,且直接在服务器上拥有本地玩家。此模式通常用于临时合作和竞技多人游戏。
专属服务器 (Dedicated Server)游戏作为主持网络多人游戏会话的服务器运行。其接受远程客户端中的连接,但无本地玩家,因此为了高效运行,其将废弃图形、音效、输入和其他面向玩家的功能。此模式常用于需要更固定、安全和大型多人功能的游戏。

DS和LS区别

(Dedicated Server)和监听服务器(Listen Server)

方面独立服务器(Dedicated Server)监听服务器(Listen Server)
主机独立服务器,不需要玩家主机服务器和客户端合并在一起
与玩家的依赖独立于玩家;不受玩家加入或退出的影响需要托管玩家在线
操作系统可编译为Windows和Linux客户端的操作系统
可视化表示没有可视部分,没有UI,PlayerController或Character需要UI,PlayerController和Character
连接性可在具有固定IP地址的云服务器上运行玩家连接到客户端的IP地址
IP地址问题玩家连接到固定IP,没有动态IP问题由于客户端的IP更改,玩家可能面临动态IP问题
OnlineSubsystem的使用可以使用OnlineSubsystem解决IP问题也可以使用OnlineSubsystem解决动态IP问题

GamePlay网络职责

头像
GamePlay框架中各自对应的网络职责划分(大佬的图)

DS(Dedicated Server)服务器网络模型

头像
专用服务器的下的网络模型

RPC|Remote Procedure Calls

头像
你说客户端没有什么权限,客户端总得发送我的按键消息吧!
头像
是的,客户端总得通过一个方法去告诉服务器自己的行为,我们把这个过程称为RPC.

"RPC" 是 "Remote Procedure Call"(远程过程调用)的缩写。它是一种通信协议和编程模型, 用于在不同的计算机或进程之间调用远程服务或函数,就像调用本地函数一样。

头像
SO!UE中该怎么让客户端生成的Actor能同步到服务器呢?
头像
理解还是有误!客户端并没有直接权限生成Actor(客户端不可靠)。

注意这里的服务器描述可能不准确,LS确实是生成球体,而DS模式可能只是生成球体的代理。

头像
现在康康你原本的思路。

解决|RPC调用

BP

头像
UE的BP中,可以在自定义事件中标记RPC状态,默认是不复制的。
头像
确保Actor本身可以复制,定义一个在服务器上执行的事件。
头像
搜嘎!客户端申请服务器生成这个Actor,然后自动同步给其他客户端。
GIF

C++

   // .h
   UFUNCTION(Server, Reliable)
   void ServerSetHealth();

   // .cpp
   void AMyActor::ServerSetHealth_Implementation()
   {
     //spawn的代码
   }
头像
一些变量比如速度如何同步呢?
头像
请看下一章。

扩展阅读

光环网络同步
光环网络同步

《守望先锋》中的网络脚本武器和能力open in new window

大佬博客open in new window

官方论坛open in new window