UE4用按以下顺序规则来决定玩家的相关集。这在虚函数‘AActor::IsNetRelevantFor()’中实现。
1.如果Actor是‘bAlwaysRelevant’,是由Pawn或者PlayerController拥有,是一个Pawn,或者是一个动作煽动者如噪音或伤害提供者的话,它总是相关性的。
2.如果Actor有一个拥有者并且是‘bNetUserOwnerRelevancy’的,那么使用所有者相关性。
3.如果Actor是‘bOnlyRelevantToOwner’且没有符合上述第一条,则它是非相关性的。
4.如果Actor附着在另一个Actor的骨架上,那它的相关性由它base根基的相关性决定。
5.如果Actor是隐藏的(bHidden==true)且与根组件没有相连,那么此Actor是非相关性的。
○如果没有根组件,‘AActor::IsNetRelevantFor()’会记录一个警告并询问Actor是否应设置成‘bAlwaysRelevant=true’。
6.如果‘AGameNetworkManager’被设置为基于距离的相关性,如果Actor比剔除距离近,则相关。
NOTE:因为Pawn和PlayerController重写了‘AActor::IsNetRelevantFor()’,会有不同的相关性。
优先级
UE4用负载平衡技术排列Actors优先级,并根据它对游戏的重要程度公平地分配一份带宽。
Actors有一个浮点变量叫‘NetPrioity’,值越大,拥有越高带宽。设置‘NetPrioity’为2.0的Actor会比设置成1.0的Actor频繁更新2倍。
优先级的比例较为重要。当然你不可以将全部优先级增大来提升UE4网络性能。
Actor当前优先级是根据虚函数‘AActor::GetNetPriority()’来计算的。
避免饿死,‘AActor::GetNetPriority()’会将‘NetPriority’值和Actor被最后一次复制后的等待时间相乘。
‘GetNetPriority’还需考虑Actor和Viewer之间的相对位置和距离。
大部分设置可以在蓝图的类默认值里面找到,当然,也可在每个Actor子类的c++类中设置。
-
本地Actor和远端Actor
对于Actor复制,我们还有两个更重要的属性。
这两个属性告诉你:
1.谁有这个Actor的主导权
2.这个Actor是否被复制
3.复制的模式
我们要确定的第一件事,特定Actor的主导权属于谁。
若要确定当前运行的引擎实例是否有主导权,检查这个角色的ROLE_Authority属性。如果它有主导权,那么这个引擎实例有这个Actor的掌控权(无论它是否被复制)。
NOTE:这和所有权不一样。
本地角色和远端角色逆转
本地角色和远端角色可以根据检查值逆转。
例如,在服务器上有这个配置:
Role==Role_Authority RemoteRole=ROLE_SimulatedProxy
那客户端会看到这样的:
Role==ROLE_SimulatedProxy RemoteRole==ROLE_Authority
这很有意义,因为服务器掌控这个Actor并将其复制到客户端。
而客户端只需要接受更新,并根据更新模拟Actor改变。
复制模式
服务器不会每次都更新Actor。因为将会用过多的带宽和CPU资源。相反,服务器将根据‘AActor::NetUpdateFrequency’指定的频率将属性复制给Actor。
意味着,客户端更新Actor时,将会占用一段时间。结果会导致Actor的运动断断续续。
为了补偿这点,客户端会模拟Actor两次更新之间的运动。
有两种模拟类型:
ROLE_SimulatedProxy和ROLE_AutonomousProxy
ROLE_SimulatedProxy
这会模拟Actor最后一次更新的动作推断接下来的运动轨迹。
当服务器向指定Actor发送更新时,客户端会在更新期间,根据Actor位置和新位置还有上次更新从服务器中获得的速度来继续移动Actor。
根据最后一次更新的速度和方向来模拟Actor只是其中一个模拟的例子。
你也可以在服务器更新期间自定义你推断即将进行的操作。
ROLE_AutonomousProxy
这通常只用于PlayerController所有者。
意味着Actor一直在接受玩家输入操作,那么我们在推断的时,将会拥有更多的信息来弥补推断结果(而不仅仅是通过上次更新的末速度来模拟动作)
畅游多人游戏
无缝旅游(无缝加载)
‘无缝’旅游和‘非无缝’旅游很简单区分。
‘无缝’旅游是一种非阻塞操作,‘非无缝’旅游是阻塞调用。
对客户端来说,‘非无缝’旅游意味着它将在加载新地图时与同一服务器断开重连。
UE建议多用‘无缝’旅游,因为这将体验的更加流畅,还有可以避免重连的过程导致的任何问题。
必须使用‘非无缝’旅游的三个情景:
1.第一次加载地图
2.客户端第一次连接到服务器
3.结束一个多人游戏并重新开始一个
主要旅游方法
驱动旅游有三种方法:
UEngine::Browse
○加载一个新地图
○总会导致‘无缝’旅游
○将会使服务器断开到客户端的连接去加载下一地图
○客户端会与当前服务器断开
○专用服务器不能加载到其他服务器,所以地图必须在专用服务器本地(不能根据地址跳转服务器)
UWorld::ServerTravel
○仅针对服务器
○跳转到另一张新地图
○所以连接的客户端都会跟着跳转
○多人游戏跳转地图的方式,服务器是调用这个方法的唯一掌控者
○服务器将会向所有连接的客户端调用‘APlayerController::ClientTravel’
APlayerController::ClientTravel
○从客户端调用的话,将会加载到新服务器
○从服务器调用的话,会指示连接的客户端加载到新地图(但要保持和当前服务器相连)