Replication
什么是复制?
复制就是服务器向客户端发送信息/数据的行为。
这可能局限于特定的实体和组。
蓝图基本上靠设定受影响的AActor来执行复制。
Actor是复制属性的起始类。
前文提到的所有类在某种程度上都继承自Actor类,使它们在需要时复制属性。
但也不是全部类都用这样的方法。
例如GameMode类就完全不是用复制的,它只存在于服务器上。
怎么用复制
复制可以在Actor子类的默认/构造函数里面激活:
-
‘bReplicates’被设为true的actor会在生成时复制到所有客户端上生成。
而且只有在服务器上生成时才使用。
如果在客户端生成这个actor,那么这个actor就只存在于这个客户端上了。
复制的属性
当使用复制时,我们可以复制变量。有很多种办法去实现它。我们从最常用的一种开始:
在‘Replication’下拉菜单中选择‘Replicated’将会确保这个变量会被复制到这个Actor的所有复制对象中。
当然这些Actors也要被设定为可复制。
在4.14版本中,甚至在蓝图里面,变量也可以在特定条件下被复制。想了解这些条件,请往下阅读。
复制的变量会在右上角有两个白圈圈,如图。
用C++复制变量需要在开始时做更多的工作,但它也允许我们把变量指定复制给谁。
cpp文件会拥有这个‘GetLifetimeReplicatedProps’函数。这个函数的声明已经通过一些UE4宏提供了,所以我们不需要操心声明。这里你可定义你需要复制变量的规则。
-
你同样可以使用条件复制:
-
Condition | Description |
COND_InitialOnly | 这个属性只会在初始化时尝试发送 |
COND_OwnerOnly | 这个属性只会发送给Actor的拥有者 |
COND_SkipOwner | 这个属性会发送给拥有者除外的所有连接者 |
COND_SimulatedOnly | 这个属性只会发送给模拟Actor |
COND_AutonomousOnly | 这个属性只会发送给自治Actor |
COND_SimulatedOrPhysics | 这个属性会发送给模拟或bRepPhysics的Actors |
CONDInitialOrOwner | 这个属性会在初始包发送,或发送给Actor的拥有者 |
CONDCustom | 这个属性没特定条件,但需能通过SetCustomIsActiveOverride切换开关 |
重点在于理解整个RPC过程只从服务器发送到客户端,而不是循环往返工作。
我们待会学习如果将客户端上想分享给他人的信息(如PlayerName)通过RPC来复制。
复制下拉菜单的另一版本叫‘RepNotify’。
它使用一个函数,当变量更新值时,会通知所有实例。
使用此方法,你可以在值被复制后调用需要调用的逻辑。
在蓝图中,此函数会在Replication下拉菜单选择‘RepNotify’立刻自动生成。
C++版本需要多点内容,但工作原理一样:
-
通过‘ReplicatedUsing=FUNCTIONNAME’语句,我们指定在变量成功复制时函数将被调用。
这个函数需要‘UFUNCTION()’宏,即使是空函数。
远程过程调用RPC
另一种叫法是“RPC”,‘远程过程调用’的缩写。
用于调用在其他实例上的方法。就像电视遥控和电视机一样。
UE4用RPC来调用从客户端到服务器、从服务器到客户端、或从服务器到特定组的函数。
这些RPC调用不能有返回值!如果你要返回某些数据,你得用另一个RPC调用。
但这只适用于特定规则。规则如下:
1.Run on Server —— 意味着在服务器Actor实例上运行
2.Run on owning Client —— 意味着在Actor拥有者上运行
3.NetMulticast —— 意味着在所有Actor实例上运行
要求和注意事项
有几个RPC调用需要满足的要求:
1.调用者必须是Actor
2.Actor必须是replicated属性的
3.如果RPC被服务器调用,在客户端上执行,那么则只有该Actor的拥有者才会执行这个函数。
4.如果RPC被客户端调用,在服务器上执行,那么客户端必须拥有调用RPC的参与者。
5.多播RPC是个例外:
(1)如果从服务器调用,则服务器会本地执行以及当前连接的所有客户端都会执行。
(2)如果从客户端调用,他们会在客户端本地执行,但不会在服务器上执行。
(3)现在,我们有一个简单的关于多播事件的节流机制:一个多播函数,在一个给定的Actor网络更新周期里,不会被复制超过两次。长期来看,我们希望在这方面有所改进。
从服务器调用RPC
Actor拥有权 | 不被复制 | 多播 | 服务器 | 客户端 |
客户端Actor | 在服务器执行 | 在服务器和所有客户端上执行 | 在服务器执行 | 在Actor拥有权客户端执行 |
服务器Actor | 在服务器执行 | 在服务器和所有客户端上执行 | 在服务器执行 | 在服务器执行 |
未知Actor | 在服务器执行 | 在服务器和所有客户端上执行 | 在服务器执行 | 在服务器执行 |
从客户端调用RPC
Actor拥有权 | 不被复制 | 多播 | 服务器 | 客户端 |
属于调起客户端 | 在调起客户端上运行 | 在调起客户端上运行 | 在服务器上运行 | 在调起客户端上运行 |
属于其他客户端 | 在调起客户端上运行 | 在调起客户端上运行 | 丢失 | 在调起客户端上运行 |
服务器Actor | 在调起客户端上运行 | 在调起客户端上运行 | 丢失 | 在调起客户端上运行 |
未知Actor | 在调起客户端上运行 | 在调起客户端上运行 | 丢失 | 在调起客户端上运行 |