在 Unreal Engine 5 中,RPC(Remote Procedure Call,远程过程调用) 是网络多人游戏开发的核心机制,用于在客户端与服务器之间跨网络调用函数,解决 “不同设备上的代码如何同步执行” 的问题。
一、核心作用
在多人游戏中,客户端(玩家设备)和服务器(权威节点)是独立运行的程序。RPC 的作用是:
- 让客户端调用服务器上的函数(比如 “玩家开枪” 需要服务器验证并同步给其他玩家);
- 让服务器调用客户端上的函数(比如 “只告诉特定玩家的任务提示”);
- 实现 “一次调用,多端执行”(比如 “播放一个所有玩家都能看到的爆炸特效”)。
二、三种 RPC 类型及适用场景
UE5 中 RPC 分为三类,通过函数宏(
UFUNCTION
)的关键字区分,核心区别在于 “谁调用、谁执行”:1. Server RPC(客户端→服务器)
- 定义:客户端调用,仅在服务器上执行。
- 宏标记:
UFUNCTION(Server, Reliable/Unreliable)
- 适用场景:客户端需要向服务器提交 “需要权威验证” 的操作,比如:
- 玩家移动、攻击、拾取物品(防止客户端作弊,需服务器确认);
- 提交任务进度、购买物品(需服务器记录数据)。
- 注意:
- 只能由拥有网络角色(Net Role)为
ROLE_AutonomousProxy
的客户端调用(通常是本地玩家控制的 Actor); - 必须实现函数体(服务器端执行的逻辑),且通常需要在函数内做权限检查(
HasAuthority()
)。
- 只能由拥有网络角色(Net Role)为
2. Client RPC(服务器→客户端)
- 定义:服务器调用,仅在指定客户端上执行。
- 宏标记:
UFUNCTION(Client, Reliable/Unreliable)
- 适用场景:服务器向特定客户端发送 “仅该客户端需要的信息”,比如:
- 向玩家显示个人任务提示、UI 通知;
- 同步只有本地玩家能看到的特效(如瞄准镜镜头)。
- 注意:
- 由服务器调用,需指定目标客户端(通常通过
AActor*
的GetOwner()
或Controller
确定); - 客户端需实现函数体(客户端执行的逻辑)。
- 由服务器调用,需指定目标客户端(通常通过
3. Multicast RPC(服务器→多端)
- 定义:服务器调用,在服务器自身 + 所有相关客户端上执行。
- 宏标记:
UFUNCTION(NetMulticast, Reliable/Unreliable)
- 适用场景:需要 “全网同步” 的操作,所有设备都要执行相同逻辑,比如:
- 播放爆炸特效、播放全局音效(所有人都能看到 / 听到);
- 同步关卡内的动态变化(如门打开、桥梁坍塌)。
- 注意:
- 仅服务器能发起调用(客户端调用无效);
- 会自动在服务器和所有 “拥有该 Actor 网络副本” 的客户端上执行。
三、关键概念:可靠性(Reliable/Unreliable)
RPC 必须指定可靠性,影响网络传输方式:
- Reliable(可靠):
保证数据一定送达(通过重传机制),但可能有延迟。
适合关键逻辑(如玩家攻击、任务提交)。 - Unreliable(不可靠):
不保证送达(丢包不重传),但速度快、延迟低。
适合实时性高但非关键的内容(如角色动画状态、临时特效)。
四、使用条件与限制
- 仅支持 Actor 类:RPC 函数必须定义在
AActor
或其派生类中(因 Actor 有网络标识NetID
,用于定位目标设备)。 - 参数需可序列化:函数参数必须是 UE 支持网络序列化的类型(如
FVector
、FString
、int32
,或自定义的FStruct
并标记USTRUCT(BlueprintType)
)。 - 避免过度使用:RPC 会占用网络带宽,频繁调用(如每帧调用)可能导致卡顿,优先用 “属性同步(Replication)” 处理状态同步。
- 权限检查:Server RPC 中需用
if (HasAuthority())
确认服务器身份,防止客户端伪造调用。
- 代码介绍
- // 在玩家角色类(APlayerCharacter)中定义Server RPC
- UCLASS()
- class MYGAME_API APlayerCharacter : public ACharacter
- { GENERATED_BODY()
- public:
- // 客户端调用,服务器执行:玩家开枪 UFUNCTION(Server, Reliable, WithValidation)
- // WithValidation 启用参数验证 void Server_Fire();
- protected:
- // 服务器端执行的逻辑(实际开枪逻辑) virtual void Server_Fire_Implementation();
- // 参数验证(可选,防止恶意数据) virtual bool Server_Fire_Validate(); }; // 实现 void APlayerCharacter::Server_Fire_Implementation() { if (HasAuthority())
- // 确认在服务器 { // 执行开枪逻辑(如射线检测、扣血) FireWeapon();
- // 同步给所有客户端(可选,用 Multicast RPC) Multicast_PlayFireEffect(); } }
- bool APlayerCharacter::Server_Fire_Validate()
- {
- // 简单验证:比如检查玩家是否有子弹
- return CurrentAmmo > 0;
- }