完成目标:主机创建房间并得到加入码,客户端加入后由 NGO 建立连接,主机统一加载游戏场景,双方可以安全离开并回到主菜单。
项目结构1. 场景准备2. 完整流程控制器3. UI 调用方式4. 为什么不要手动 StartHost5. 网络场景切换6. 状态机比布尔值更稳7. 断线和恢复8. 服务端权威边界9. 测试矩阵功能错误网络构建10. 上线前检查系列导航参考资料
项目结构
建议把职责拆开:
- UI:读取输入、显示加载和错误状态
- MultiplayerFlow:编排 UGS、Session 和离开流程
- NGO NetworkBehaviour:同步具体玩法
- NetworkSceneManager:由服务器切换网络场景
UI 不应直接调用 Lobby、Relay 和
NetworkManager 的多套底层接口。1. 场景准备
创建两个场景并加入 Build Profiles:
MainMenu
Game
在 MainMenu 放置:
- 配置了
UnityTransport的NetworkManager
MultiplayerFlow
- Host 按钮、Join 按钮、加入码输入框、状态文本
Player Prefab 必须有
NetworkObject,并配置到 NetworkManager。2. 完整流程控制器
3. UI 调用方式
Unity Button 不能直接显示绑定返回
Task 的方法。可以在 Presenter 中用很薄的 async void 事件入口,并在内部捕获异常:async void 只留在 UI 事件边界;业务方法返回 Task,这样才能等待、测试和传播异常。4. 为什么不要手动 StartHost
CreateSessionAsync(...WithRelayNetwork()) 使用默认网络处理器时,会配置 Relay 与 Unity Transport,并启动 NGO Host。JoinSessionByCodeAsync 会启动 NGO Client。若随后又调用
NetworkManager.StartHost() 或 StartClient(),就可能重复启动网络栈。只有实现自定义 Network Handler 时,才自行接管这些步骤。5. 网络场景切换
联机游戏不要让每个客户端各自调用普通
SceneManager.LoadScene。由服务器调用 NGO 的 NetworkSceneManager.LoadScene,客户端才会按同一网络流程加载场景并同步 NetworkObject。开始按钮还应验证:
- 当前调用方是 Server / Host
- 所有玩家已准备
- Session 未锁定或处于正确阶段
- 目标场景已加入 Build Profiles
6. 状态机比布尔值更稳
示例用
IsBusy 保持简洁。生产项目建议建立明确状态:每个 UI 控件根据状态决定是否可用,能避免“正在加入时再次创建房间”之类的竞态。
7. 断线和恢复
至少处理三类情况:
- 主动离开:调用
ActiveSession.LeaveAsync()
- 网络断开但仍是成员:查询已加入 Session,并按官方 Reconnect 流程恢复
- Host 消失:结束当前对局,或进入完整 Host Migration 流程
不要在
OnApplicationQuit 中假设异步请求一定能完成。关键状态应在正常 UI 离开流程中提交;异常退出由后端超时和会话生命周期兜底。8. 服务端权威边界
连接成功只代表玩家能通信。所有影响游戏结果的操作仍应由服务器验证:
- 移动速度和位置变化
- 攻击冷却、弹药和命中
- 道具拾取距离
- 金币、经验和胜负
客户端发送意图,服务器修改
NetworkVariable 或生成 NetworkObject。Relay 不会替你做这些验证。9. 测试矩阵
功能
- Host 创建并显示加入码
- Client 加入后生成两个 PlayerObject
- 只有所有者能控制自己的对象
- Host 统一加载 Game 场景
- Client 离开后成员和对象被清理
错误
- 空加入码、错误加入码、房间已满
- 快速重复点击 Host / Join
- 初始化失败、认证失败、网络断开
- Host 在大厅和游戏中分别退出
网络
- 100–300 ms 延迟
- 丢包和抖动
- 移动端切后台再恢复
- Wi-Fi 与移动网络切换
构建
- Editor 两实例
- 两个独立本地 Build
- 至少一次真实异地网络测试
- 每个目标平台的 IL2CPP Build
10. 上线前检查
- 认证账号可恢复,不只依赖匿名本地令牌
- 处理 DSA 通知 API 与隐私要求
- 核对 Lobby / Relay 费率、限流和区域
- 日志不输出访问令牌或敏感玩家数据
- 监控创建、加入、断线和平均会话时长
- 为服务不可用准备明确的离线提示
- 确认 Host 模式的作弊风险符合产品定位