1.1 服务器权威模型:为什么你的血量不能客户端说了算
一个真实的事故
我曾接手过一个半成品 ARPG 联机 demo:为了「打击感好」,前作者把伤害计算放在客户端——客户端检测到剑碰到怪物,直接扣怪物血、播受击特效,再通知服务器结果。单机测试手感确实棒,联机第一天就炸了:两个玩家同时砍同一只怪,各自客户端算出不同伤害,服务器不知道该信谁;更糟的是有人改本地内存把攻击力改成 99999,服务器没做校验,全服广播——BOSS 秒杀,存档崩坏。
这不是段子,这是所有「客户端权威」设计的必然结局。UE 从架构层面默认推崇服务器权威(Server Authority):服务器才是游戏世界唯一合法的状态来源,客户端看到的只是一份「尽可能新的复印件」。
权威模型的分工
在服务器权威模型下,三端职责清晰分离:
| 端 | 职责 | 不允许做的事 |
|---|---|---|
| 服务器 | 持有真实状态,运行游戏逻辑,裁决一切规则 | 无(它是裁判) |
| 本地客户端 | 采集输入,渲染画面,做乐观预测 | 修改权威状态(只能请求) |
| 远程客户端(其他玩家) | 接收复制数据,插值渲染 | 直接参与逻辑判定 |
注意「本地客户端」和「远程客户端」都是客户端,区别只是:本地客户端上运行的 Pawn 是你操纵的那个,它的输入会发给服务器;远程客户端上你的角色只是个「由复制数据驱动的提线木偶」。
为什么必须这样
三个理由,按权重排序:
- 反作弊。客户端是不可信的,内存可改、封包可伪造。任何客户端能直接改变的权威数据,都等于外挂入口。服务器权威把作弊面收窄到「服务器代码有 bug」这一个口子。
- 一致性。多个客户端各自演算,浮点误差、时序差异会让世界分叉。伤害判定、命中检测这类「必须全服一致」的逻辑,只能放服务器。
- 可预测的调试。出问题时只需看服务器这一份状态,不需要在 N 个客户端版本之间对账。
例外:什么时候可以让客户端「说了算」
服务器权威不是宗教,有些场景客户端权威(或混合权威)才是正解:
- 纯粹的本地表现:镜头抖动、武器轨迹粒子、本地-first 的动画混合。这些不影响共享状态,放客户端做能省带宽、降延迟。
- 乐观预测:客户端先本地执行移动,服务器事后校正——这就是 CharacterMovement 的客户端预测机制(第四章详讲)。注意预测的只是「执行」,裁决权仍在服务器。
- 临时性、可被覆盖的表现:比如受击闪红,客户端先播,服务器随后校正真正的血量。
- 休闲/合作 PVE,且你对反作弊零要求。即便如此,也建议留好权威开关,后期转 PVP 不至于推倒重来。
落地:脑内检查清单
写任何联网逻辑前,过一遍这三个问题:
- 「这个数据修改后,别的玩家需要看到吗?」——不需要,纯本地;需要,走服务器。
- 「如果客户端伪造这个数据,最坏后果是什么?」——后果能接受(例如客户端只请求「我想挥剑」,服务器裁决命中),OK;不可接受(客户端说「我造成了 999 伤害」),必须服务器算。
- 「服务器拒绝时,客户端体验是什么?」——设计好回滚/校正表现,否则就是「瞬移」「卡顿」的体感来源。
心得:把服务器权威理解成「状态所有者单一」而非「逻辑全部上服务器」。该放客户端的表现层逻辑就放,但共享状态只有一个权威来源。这个边界划得越早,后期重构越少。
