目录
- 0 引言
- 1 Network Role and Authority(网络角色和授权)
- 1.1 Authority (权威角色 / 权威端)
- 1.2 Simulated Proxy (模拟代理 / 模拟端)
- 1.3 Autonomous Proxy (自主代理 / 主动端)
- 1.4 示例:多人塔防游戏中的 NetRole
- 2 Actors and their Owning Connections(Actor 所有权)
- 2.1 定义
- 2.2 所有权的作用
- 2.3 示例:多人塔防游戏
- 3 Actor Role and RemoteRole (Actor 角色)
- 3.1 `Actor Role`
- 3.2 `RemoteRole`
- 3.3 确定主控权
- 3.4 复制模式
- 3.5 示例
- 3.6 总结
- 4 网络角色和Actor角色的区别和联系
- 🙋♂️ 作者:海码007
- 📜 专栏:UE虚幻引擎专栏
- 💥 标题:【UE 网络】Network Role and Authority、Actors Owner、Actor Role and RemoteRole
- ❣️ 寄语:书到用时方恨少,事非经过不知难!
- 🎈 最后:文章作者技术和水平有限,如果文中出现错误,希望大家能指正,同时有问题的话,欢迎大家留言讨论。
0 引言
了解Actor复制中的,网络角色和授权、客户端拥有权、Actor 及其关联连接、Actor Role(Actor 角色)和RemoteRole。有助于深入的理解UE的网络框架。文档中讲述的都是一些理论,如果要真正的深入了解,还需要从具体的业务出发。
官方文档
安宁Ken视频教程
1 Network Role and Authority(网络角色和授权)
官方文档的解释:
An Actor’s network role
determines whose machine has control over the Actor during a network game. An authoritative Actor
is considered to have control over that Actor’s state, and will replicate information to other machines within the network multiplayer session. A remote proxy
is a copy of that Actor on a remote machin
e, and it receives replicated information from the authoritative Actor
. This is tracked by the Local Role
and Remote Role
variables, which can take the following values:
翻译:
Actor的 网络角色 将决定网络游戏期间控制 Actor 的机器。授权(Authority) Actor 被认为可控制Actor的状态,并可将信息复制到网络多人游戏会话中的其他机器上。远程代理(remote proxy) 是该Actor在远程机器上的副本,其将接收 授权(Authority)Actor 中的复制信息。其由 Local Role 和 Remote Role 变量进行追踪,可取以下值:
虚幻引擎使用的默认模型是 服务器授权,意味着服务器对游戏状态固定具有权限,而信息固定从服务器复制到客户端。服务器上的Actor应具有授权的本地角色,而其在远程客户端上的对应Actor应具有模拟或自主代理的本地角色。
1.1 Authority (权威角色 / 权威端)
Authority Actor,又叫做权威端。指的是服务器上的 Actor。服务器是游戏的权威,负责管理和验证所有的游戏状态和操作。
- 服务器控制:Authority Actor在服务器上有完全的控制权,所有的游戏逻辑和状态更新都在服务器上进行。
- 状态验证:服务器会验证客户端发送的请求和操作,确保游戏的公平性和一致性。
- 广播更新:服务器会将更新后的状态广播给所有相关的客户端,确保所有客户端的游戏状态保持一致。
1.2 Simulated Proxy (模拟代理 / 模拟端)
Simulated Proxy Actor通常用于客户端上的非自主 Actor 。这些 Actor 在客户端上进行模拟,但最终的状态由服务器决定。
- 客户端模拟:Simulated Proxy Actor 在客户端上进行模拟,以提供即时的反馈和流畅的游戏体验。
- 服务器同步:尽管客户端进行模拟,最终的状态还是由服务器决定并同步到客户端。
- 减少延迟感:通过在客户端进行模拟,可以减少网络延迟带来的影响,使游戏体验更加流畅。
1.3 Autonomous Proxy (自主代理 / 主动端)
Autonomous Proxy Actor 通常用于客户端拥有的 Actor ,例如玩家控制的角色(Player Character)。这种 Actor 在客户端上有更多的控制权,并且可以自主地进行一些操作。在UE4的网络架构中,主动端(Autonomous Proxy)主要用于玩家角色
,以便直接响应玩家输入并进行本地预测。
- 客户端控制:Autonomous Proxy Actor 在客户端上有更多的控制权,允许客户端直接对 Actor 进行输入和操作。
- 本地预测:客户端可以进行本地预测,以减少网络延迟带来的影响。例如,玩家移动时,客户端可以立即显示移动效果,而不必等待服务器的确认。
- 同步到服务器:尽管客户端有更多的控制权,但最终的状态还是需要同步到服务器,服务器会进行验证和纠正。
1.4 示例:多人塔防游戏中的 NetRole
在一个多人塔防联机游戏中,两个客户端(A和B)以及服务器的NetRole是如何分配和工作的。假设我们有一个多人塔防游戏,玩家可以在地图上放置防御塔来抵御敌人的进攻。每个玩家控制一个角色,可以在地图上移动并放置防御塔。我们有两个客户端(A和B)和一个服务器。
一、角色和对象
- 玩家角色(Player Character):每个客户端控制一个玩家角色。
- 防御塔(Tower):玩家可以在地图上放置的防御塔。
- 敌人(Enemy):敌人会沿着路径进攻,玩家需要使用防御塔来消灭敌人。
二、不同对象的Network Role
下面来分析一下每个对象在不同机器上的NetRole。
-
玩家角色(Player Character):
- 客户端A的玩家角色在客户端A上是主动端(Autonomous Proxy),这意味着客户端A可以直接控制自己的角色,并进行本地预测。
- 客户端B的玩家角色在客户端A上是模拟端(Simulated Proxy),这意味着客户端A会接收服务器的更新并进行模拟。
- 在服务器上,所有玩家角色都是权威端(Authority),服务器负责管理和验证所有玩家角色的状态和操作。
-
防御塔(Tower):
- 所有防御塔在客户端上都是模拟端(Simulated Proxy),这意味着客户端会接收服务器的更新并进行模拟。
- 在服务器上,所有防御塔都是权威端(Authority),服务器负责管理和验证所有防御塔的状态和操作。
-
敌人(Enemy):
- 所有敌人在客户端上都是模拟端(Simulated Proxy),这意味着客户端会接收服务器的更新并进行模拟。
- 在服务器上,所有敌人都是权威端(Authority),服务器负责管理和验证所有敌人的状态和操作。
三、数据流和同步的过程
- 玩家输入:客户端A和客户端B的玩家输入(例如移动和放置防御塔)会发送到服务器。服务器验证这些输入并更新游戏状态。
- 状态更新:服务器将更新后的游戏状态(例如玩家位置、防御塔位置、敌人位置)广播给所有客户端。
- 客户端模拟:客户端接收到服务器的更新后,会在本地进行模拟,以提供即时的反馈和流畅的游戏体验。
四、总结
- 在UE4的网络架构中,
主动端(Autonomous Proxy)主要用于玩家角色
,以便直接响应玩家输入并进行本地预测。其他对象(如防御塔、敌人等)通常只需要在客户端进行模拟(Simulated Proxy),而服务器作为权威端(Authority)来管理和验证它们的状态。 - 通过合理地分配和管理NetRole,可以确保游戏的高效网络同步和流畅的游戏体验。服务器作为权威端(Authority),负责管理和验证所有的游戏状态和操作。客户端上的主动端(Autonomous Proxy)和模拟端(Simulated Proxy)则负责处理玩家输入和进行本地模拟。这样可以有效减少网络延迟带来的影响,并确保游戏的一致性和公平性。
2 Actors and their Owning Connections(Actor 所有权)
直接翻译的话是:Actor及其关联连接。但是通常叫做Actor 所有权或拥有权比较多。
官方文档
安宁Ken
2.1 定义
Actor所有权决定了一个Actor的生命周期、网络复制行为以及权限管理。Owner是指向另一个Actor的指针,表示当前Actor的所有者。每个Actor都可以有一个Owner,可以是另一个Actor或者PlayerController。
2.2 所有权的作用
所有权(Connection Ownership)在UE4中的作用非常重要,特别是在多人游戏的网络同步和权限管理方面。具体作用和机制如下:
-
RPC 执行的客户端确定:
- 当在一个
Actor
上调用远程过程调用(RPC)函数时,UE4需要知道在哪个客户端上执行该RPC。除非RPC被标记为多播(Multicast),否则需要通过连接所有权来确定目标客户端。 - 连接所有权允许引擎查找关联的连接,以确定将RPC发送到哪条连接。
- 当在一个
-
Actor 复制与连接相关性:
- 在Actor复制期间,连接所有权用于确定哪些连接应该接收特定Actor的更新。
- 对于那些将
bOnlyRelevantToOwner
设置为true
的Actor,只有拥有此Actor的连接才会接收该Actor的属性更新。 - 例如,默认情况下,所有
PlayerController
都设置了bOnlyRelevantToOwner
标志,因此客户端只会收到它们拥有的PlayerController
的更新。这有助于防止玩家作弊并提高网络效率。
-
Actor 属性复制条件:
- 连接所有权还影响Actor属性的复制条件。某些属性可能只会复制给拥有该Actor的连接。
- 这在多人游戏中非常重要,因为它可以确保只有授权的客户端才能接收到和修改特定的游戏状态。
详细机制
1. RPC 执行的客户端确定
当在服务器上调用一个RPC函数时,服务器需要知道将该RPC发送到哪个客户端。连接所有权通过以下方式实现这一点:
- 查找关联连接:服务器通过Actor的所有者(Owner)查找关联的客户端连接。
- 发送RPC:服务器将RPC发送到找到的客户端连接上。
例如:
// 在服务器上调用一个RPC函数
void AMyActor::ServerFunction_Implementation()
{// 服务器逻辑// 查找所有者的连接并发送RPCif (APlayerController* PC = Cast<APlayerController>(GetOwner())){PC->ClientFunction();}
}
2. Actor 复制与连接相关性
在Actor复制期间,连接所有权用于确定哪些连接应该接收特定Actor的更新:
- bOnlyRelevantToOwner:如果一个Actor的
bOnlyRelevantToOwner
标志设置为true
,则只有拥有此Actor的连接才会接收该Actor的属性更新。 - PlayerController:默认情况下,所有
PlayerController
都设置了bOnlyRelevantToOwner
标志,因此客户端只会收到它们拥有的PlayerController
的更新。
例如:
// 设置Actor的bOnlyRelevantToOwner标志
AMyActor::AMyActor()
{bOnlyRelevantToOwner = true;
}
3. Actor 属性复制条件
连接所有权还影响Actor属性的复制条件。某些属性可能只会复制给拥有该Actor的连接:
- 属性标记:可以使用属性标记来控制属性的复制条件。例如,
ReplicatedUsing
标记可以用于指定一个函数,当属性复制时调用该函数。 - 条件复制:可以在属性复制函数中检查连接所有权,以决定是否复制属性。
例如:
// 属性复制函数
void AMyActor::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{Super::GetLifetimeReplicatedProps(OutLifetimeProps);// 只复制给所有者DOREPLIFETIME_CONDITION(AMyActor, MyProperty, COND_OwnerOnly);
}
4. 总结
所有权在UE4中对于RPC执行、Actor复制和属性复制条件至关重要。它确保了RPC函数在正确的客户端上执行,控制了Actor的属性更新发送到哪些连接,并且在多人游戏中提供了有效的权限管理和防作弊机制。通过合理地使用连接所有权,可以实现高效的网络同步和安全的游戏状态管理。
2.3 示例:多人塔防游戏
在一个多人塔防游戏中,所有权(Ownership)和连接所有权(Connection Ownership)的设计和管理对于确保游戏的流畅运行、同步和安全性至关重要。以下是一些常见的所有权情况和设计原则,适用于不同类型的 Actor
和游戏元素。
1. 玩家控制的角色(Player Characters)
- 所有权:每个玩家控制的角色(如指挥官、英雄等)应该由对应的
PlayerController
拥有。 - 连接所有权:这些角色的连接所有权也应该是对应的客户端连接,这样可以确保玩家能够控制自己的角色。
// 在玩家控制器中生成角色
void AMyPlayerController::BeginPlay()
{Super::BeginPlay();// 生成玩家角色AMyPlayerCharacter* PlayerCharacter = GetWorld()->SpawnActor<AMyPlayerCharacter>(PlayerCharacterClass);// 设置角色的所有者为玩家控制器PlayerCharacter->SetOwner(this);// 让玩家控制器控制角色Possess(PlayerCharacter);
}
2. 防御塔(Towers)
- 所有权:防御塔通常由放置它们的玩家拥有。这样可以确保玩家能够升级、出售或控制自己的防御塔。
- 连接所有权:防御塔的连接所有权应该是放置它们的玩家的客户端连接。
// 在玩家控制器中放置防御塔
void AMyPlayerController::PlaceTower(FVector Location)
{// 生成防御塔AMyTower* Tower = GetWorld()->SpawnActor<AMyTower>(TowerClass, Location, FRotator::ZeroRotator);// 设置防御塔的所有者为玩家控制器Tower->SetOwner(this);
}
3. 敌人(Enemies)
- 所有权:敌人通常由服务器拥有,因为服务器需要控制敌人的生成、移动和攻击逻辑。
- 连接所有权:敌人的连接所有权通常是服务器,这样可以确保所有客户端都能接收到敌人的更新,并且防止客户端作弊。
// 在服务器上生成敌人
void AMyGameMode::SpawnEnemy()
{// 生成敌人AMyEnemy* Enemy = GetWorld()->SpawnActor<AMyEnemy>(EnemyClass);// 设置敌人的所有者为服务器(通常不需要显式设置,因为默认就是服务器)Enemy->SetOwner(nullptr);
}
4. 子弹和投射物(Bullets and Projectiles)
- 所有权:子弹和投射物通常由发射它们的防御塔或角色拥有。这样可以确保发射者能够控制子弹的行为和效果。
- 连接所有权:子弹和投射物的连接所有权通常是发射它们的玩家的客户端连接。
// 在防御塔中发射子弹
void AMyTower::Fire()
{// 生成子弹AMyBullet* Bullet = GetWorld()->SpawnActor<AMyBullet>(BulletClass, MuzzleLocation, MuzzleRotation);// 设置子弹的所有者为防御塔Bullet->SetOwner(this);
}
5. 游戏资源(Game Resources)
- 所有权:游戏资源(如金币、经验值等)通常由服务器拥有,因为服务器需要管理和验证资源的分配和使用。
- 连接所有权:游戏资源的连接所有权通常是服务器,这样可以确保所有客户端都能接收到资源的更新,并且防止客户端作弊。
// 在服务器上管理资源
void AMyGameMode::AddResource(int32 Amount)
{// 增加资源Resources += Amount;// 通知所有客户端资源更新OnRep_Resources();
}
6. 总结
在一个多人塔防游戏中,合理地设置和管理所有权和连接所有权对于确保游戏的流畅运行、同步和安全性至关重要。玩家控制的角色和防御塔通常由对应的 PlayerController
拥有,敌人和游戏资源通常由服务器拥有。通过合理地分配所有权,可以确保游戏的各个元素能够正确地进行控制、更新和同步,从而提供良好的游戏体验。
3 Actor Role and RemoteRole (Actor 角色)
官方文档
安宁Ken
在 Actor 的复制过程中,有两个属性扮演了重要角色,分别是 Role 和 RemoteRole。有了这两个属性,您可以知道:
- 谁拥有 actor 的主控权
- actor 是否被复制
- 复制模式
首先一件要确定的事,就是谁拥有特定 actor 的主控权。要确定当前运行的引擎实例是否有主控者,需要查看 Role 属性是否为 ROLE_Authority。如果是,就表明这个运行中的 虚幻引擎 实例负责掌管此 actor(决定其是否被复制)。
3.1 Actor Role
Role
属性表示当前 Actor
在本地的角色。它可以有以下几种值:
ROLE_None
:该Actor
不参与网络复制。ROLE_SimulatedProxy
:该Actor
是一个模拟代理,通常在客户端上使用。它接收来自服务器的更新,但不能自主决定其状态。ROLE_AutonomousProxy
:该Actor
是一个自主代理,通常用于客户端拥有的Actor
。它可以自主决定其状态,并将这些状态发送到服务器。ROLE_Authority
:该Actor
拥有主控权,通常在服务器上使用。它决定Actor
的状态并将这些状态复制到客户端。
3.2 RemoteRole
RemoteRole
属性表示该 Actor
在远程(通常是服务器或客户端)上的角色。它可以有以下几种值:
ROLE_None
:该Actor
不参与网络复制。ROLE_SimulatedProxy
:该Actor
在远程是一个模拟代理。ROLE_AutonomousProxy
:该Actor
在远程是一个自主代理。ROLE_Authority
:该Actor
在远程拥有主控权。
3.3 确定主控权
要确定当前运行的引擎实例是否拥有某个 Actor
的主控权,可以检查 Role
属性是否为 ROLE_Authority
。如果是,则表明该引擎实例负责掌管此 Actor
。
if (Role == ROLE_Authority)
{// 当前实例拥有主控权
}
3.4 复制模式
通过 Role
和 RemoteRole
的组合,可以确定 Actor
的复制模式。例如:
-
服务器上的
Actor
:Role
为ROLE_Authority
RemoteRole
为ROLE_SimulatedProxy
或ROLE_AutonomousProxy
-
客户端上的
Actor
:Role
为ROLE_SimulatedProxy
或ROLE_AutonomousProxy
RemoteRole
为ROLE_Authority
3.5 示例
以下是一个示例,展示如何使用 Role
和 RemoteRole
属性来确定 Actor
的主控权和复制模式。
MyActor.h
UCLASS()
class AMyActor : public AActor
{GENERATED_BODY()public:virtual void Tick(float DeltaTime) override;protected:virtual void BeginPlay() override;
};
MyActor.cpp
#include "MyActor.h"void AMyActor::BeginPlay()
{Super::BeginPlay();if (Role == ROLE_Authority){UE_LOG(LogTemp, Log, TEXT("This instance has authority over this actor."));}else{UE_LOG(LogTemp, Log, TEXT("This instance does not have authority over this actor."));}
}void AMyActor::Tick(float DeltaTime)
{Super::Tick(DeltaTime);if (Role == ROLE_Authority){// 服务器上的逻辑}else if (Role == ROLE_AutonomousProxy){// 客户端自主代理的逻辑}else if (Role == ROLE_SimulatedProxy){// 客户端模拟代理的逻辑}
}
3.6 总结
Role
和 RemoteRole
属性在 UE4 的网络复制系统中扮演了重要角色。通过检查这些属性,可以确定当前引擎实例是否拥有某个 Actor
的主控权,以及该 Actor
的复制模式。理解和正确使用这些属性对于开发多人游戏和实现网络同步至关重要。
4 网络角色和Actor角色的区别和联系
在Unreal Engine 4(UE4)中,Network Role 和 Actor Role 是两个相关但不同的概念。
-
区别:
- Network Role 主要用于描述Actor在网络环境中的角色,决定了Actor在客户端和服务器之间的行为和职责。
- Actor Role 主要用于描述Actor在游戏逻辑中的角色,决定了Actor在游戏中的行为和职责。
-
联系:
- 在大多数情况下,Network Role 和 Actor Role 是一致的。例如,服务器上的Actor通常同时具有 ROLE_Authority 的 Network Role 和 Actor Role。
- 在客户端上,玩家控制的角色通常同时具有 ROLE_AutonomousProxy 的 Network Role 和 Actor Role。
- 非玩家控制的角色或其他对象通常同时具有 ROLE_SimulatedProxy 的 Network Role 和 Actor Role。