判断当前是在Client or Server执行方法,敏感信息应放在服务端计算,而客户端只做展示
区分当前运行的是客户端还是服务器
蓝图中,有个 SwitchHasAuthority 宏:
FORCEINLINE_DEBUGGABLE bool AActor::HasAuthority() const { return (Role == ROLE_Authority); }
- 只有 Role == ROLE_Authority 情况才是表示是 这个actor是在服务器上,其他两种情况都表示在客户端上
- Authority:如果是服务器,会走这个支线
- Remote:如果是客户端,会走这个支线
- 只有 Role == ROLE_Authority 情况才是表示是 这个actor是在服务器上,其他两种情况都表示在客户端上
c++中:
AActor 中都有个 ENetRole Role 变量是用来识别角色的 Actor 的身份的。ENetRole 的几个值:
- ROLE_None:
- ROLE_SimulatedProxy:这个actor是其他客户端在本机客户端的一个模拟代理
- ROLE_AutonomousProxy:这个actor是本机客户端的自己控制的角色
- ROLE_Authority:这个actor是服务器上的actor
示例代码
void AMyNetCharacter::BeginPlay() { Super::BeginPlay(); switch (Role) { case ROLE_Authority: Flag = "ROLE_Authority"; break; case ROLE_SimulatedProxy: Flag = "ROLE_SimulatedProxy"; break; case ROLE_AutonomousProxy: Flag = "ROLE_AutonomousProxy"; break; default: Flag = "ROLE_None"; } }
从左至右的三个角色分别是 Server、Client1、Client2 对应控制的角色
- Server 显示
- Client1 显示
- Client2 显示
- Server 显示
Actor 的 生成 和 销毁
- 如果想 生成 或 销毁 一个 Actor,这个 Actor 必须为 Replicates
- 而且必须在服务器上调用,而不是客户端调用,否则只会在该客户端生产,其他客户端不会生成
- 销毁 的类似。
区分自己控制的和别人的
方式一:经过服务,先rpc服务器方法,再调用拥有该actor控制权的客户端的方法
- CallServerChangeSkin 事件是 Run On Server 类型
- ChangeOwnSkin 事件是 Run On Owning Client 类型
方式二:直接成 Actor 中 的 Role 中判断,但不知为啥引擎不提供接口, Role 变量也没有暴露给蓝图,那么就自己提供个接口
UFUNCTION(BlueprintCallable, Category = AMyNetCharacter) virtual ENetRole GetRole() { return Role; }
结果:只有自己控制的 Actor 变色
服务端计算、客户端展示
一般来说,对于敏感数值的计算及校验都是在服务端上做,客户端则用来做展示效果,示例如下:
按 空格键 触发一个 Skill1 事件, Skill1 是个 Run On Server,只在服务器上调用的事件
- 该事件是选取范围内的 Pawn 赋予伤害触发 Apply Damage 事件
Apply Damage 是个只会在服务器上跑的事件 修改 Health 变量,该变量是个 RepNotify 类型,会对应生产一个 值改变时触发的函数 OnRep_Health(客户端服务器都会调用),
- 在 OnRep_Health 判断只有在客户端中才调 ChangeHealthText(TextRender的展示内容)
- 这里如果 Health 减到小于0时则 DestroyActor 销毁,否则触发 ShowEffect 事件
ShowEffect 事件是个 Multicast 类型,客户端服务器都会调用
- 这里只需要客户端展示,所以进一步 SwitchHasAuthority 判断,只在客户端(Remote)Spawn粒子特效
所以结果是:Health 的 TextRender展示 和 粒子特效 都只会在客户端展示,服务端只负责存储及计算值。
作者:yangxuan0261 发表于2017/1/28 15:05:40 原文链接
阅读:32 评论:0 查看评论