从 小白到处踩坑 到 逐渐搞懂 UE 网络架构

14 阅读5分钟

在 UE 联网开发中,理解每一个组件的作用范围是避免 Bug 的重要方法。我们把它们按 可见性生命周期 整理如下:

1. 核心组件分布图(谁能看到谁)

组件服务器拥有者客户端其他客户端核心职责
GameInstance✅ 有✅ 有✅ 有跨关卡数据存储(不联网)。
GameMode✅ 有❌ 无❌ 无游戏规则、胜负判定、玩家出生。
GameState✅ 有✅ 有✅ 有单局游戏全局状态(得分、进度)。
PlayerController✅ 有✅ 有❌ 无玩家私人专线(输入、私人 UI)。
PlayerState✅ 有✅ 有✅ 有玩家公共数据(名字、装备、血量)。

2. 易混点 OR 踩坑

① GameMode (游戏模式)

  • 只存在于服务器,客户端根本不知道 GameMode 的存在。

  • 核心任务

    • 决定谁能加入游戏。
    • 控制玩家在哪个点出生。
    • 判定游戏结束条件。
  • 注意:别在 GameMode 里写客户端逻辑,因为客户端获取不到它,Get GameMode 在客户端永远返回 Null

② GameInstance (游戏实例)

  • 生命周期最长,从你打开游戏进程到关闭游戏,它一直都在。

  • 非联网组件:它不参与网络复制, 服务器有一个,每个客户端也各有一个。

  • 核心任务

    • 存放关卡切换时不能丢的数据(如设置参数、未保存的角色信息)。
    • 处理网络报错提示。
  • 注意:它是本地的。如果你在客户端 A 的 GameInstance 改了变量,服务器和其他客户端完全看不见。


3. 网络执行生命周期(玩家进入流程)

当一个玩家加入正在运行的服务器时:

  1. 服务器 GameMode 收到请求,检查是否允许加入。
  2. 服务器 为其生成 PlayerControllerPlayerState
  3. 服务器 触发它们的 BeginPlay(服务器侧)。
  4. 客户端 加载地图,生成本地镜像。
  5. 客户端 触发它们的 BeginPlay(客户端侧)。
  6. 同步开始:服务器将 GameStatePlayerState 的最新数据快照同步给新玩家。

4. 变量复制模式

① Replicated (普通复制)

  • 底层原理:服务器变量值改变后,引擎会自动将新值序列化并发送给所有客户端。客户端收到后直接覆盖本地变量。

  • 适用场景

    • 非瞬时表现的数据:比如玩家的等级、称号、当前持有的金币数。
    • UI 轮询(Polling)逻辑:如果你的 UI 是每隔 0.1 秒主动去读一次变量值,用这个就够了。
  • 缺点:客户端不知道变量“什么时候”变了,只能被动接受覆盖。

② RepNotify (带回调的复制)

  • 底层原理:除了自动更新变量值,引擎还会自动生成一个名为 OnRep_变量名 的函数。当客户端收到服务器发来的数据更新时,会自动触发这个函数。

  • 适用场景

    • 驱动视觉反馈:比如“血量”变了,不仅要更新数值,还要触发红屏闪烁或播放扣血特效。
    • 刷新 UI 列表:比如你的背包数组变了,触发 OnRep 里的事件分发器,命令 UI 重新绘制列表。
  • 注意

    • 服务器默认不触发:服务器直接修改变量时,默认不会跑 OnRep 函数(除非你是服务器玩家且逻辑特殊处理)。通常需要手动在服务器逻辑后 Call 一次该函数或分发器。
    • 执行顺序:引擎保证在进入 OnRep 函数之前,本地变量已经变成了服务器同步过来的最新值。

5. 联机注意项

① BeginPlay 的执行时机

每当新玩家加入,服务器都会为该玩家生成新的 Controller 并跑一遍 BeginPlay

  • 注意:如果服务器本身也是玩家(主机玩家),它也会执行新玩家的 BeginPlay
  • 对策:初始化 UI 必须加 Is Locally Controlled 过滤,否则主机屏幕上会叠加弹起别人的 UI。

② 三类自定义事件 (RPC)

决定逻辑在谁的电脑上运行:

  • Run on Server:客户端 ➔ 服务器。用于申请改钱、扣血等权限操作。
  • Run on Owning Client:服务器 ➔ 拥有者客户端。用于发私信、震动本地手柄。
  • Multicast:服务器 ➔ 所有客户端。用于播特效、放声音、全服通告。

③ Multicast 为什么必须在 Server 执行?

  • 物理限制:客户端之间没有通路,A 无法直接命令 B 的屏幕。
  • 权限安全:服务器是唯一裁判,防止客户端非法广播。必须先 Run on Server 申请,再由服务器发起广播。

6. UI 应该如何初始化?

最稳健的写法是:

  • UI 的壳子:放在 PlayerController 里。判断 Is Locally Controlled 确保只有本地创建。
  • UI 的数据:放在 PlayerState 里。勾选 RepNotify
  • UI 的刷新:变量更新时可用事件分发器,通知执行 UI 更新。
  • 全局信息(如比赛时间) :从 GameState 获取。

7. 总结

  • GameInstance:本地记忆,跨关卡不丢,但不联网。
  • GameMode:上帝规则,只在服务器,客户端拿不到。
  • GameState:公共账本,全员可见,存大局进度。
  • PlayerController:私人遥控器,处理本地输入和 UI,初始化必加本地判断。
  • PlayerState:公共名片,全员可见,存玩家属性和装备。
  • Replicated:静默同步,适用于后台数据。
  • RepNotify:响应式同步,适用于需要即时触发动画、音效或 UI 刷新的关键变量。
  • 同步准则:向上申请(Server RPC),向下同步(OnRep / Multicast)。