5.2 玩家生命周期:从匹配加入、重连到退出

一次完整的加入流程

客户端                             服务器
  │ ClientTravel 到服务器地址
  │ ─────────地图加载 & 连接────────→
  │                                 预登录(PreLogin): ban 检查、版本检查、人数检查
  │ ←─────────── 通过/拒绝 ──────────
  │ 登录(Login): PlayerController spawn
  │ ←─────── 承载玩家(OnPostLogin)─
  │                                 GameMode 选择 Pawn、AssignPlayerState
  │ ←── 复制的世界快照(相关 Actors)─
  │ 客户端 BeginPlay,UI 初始化完毕

关键排坑点:

  1. 版本检查放 PreLogin:客户端版本号不对直接拒绝,别等加载完再踢。
  2. 数据加载顺序:PlayerState 上的持久化数据(等级、装备)由服务器在 OnPostLogin 后异步拉取(DB/WEB),加载完成前先给玩家一个观战/等待状态,别让「空数据玩家」短暂参与游戏。
  3. 重连(Reconnect):玩家网络断了重连回来。要区分「断线重连」(保留原 PlayerState、积分、位置)与「新加入」。实现:为每个玩家生成 SessionId/PlayerId,重连时按 ID 找回旧 PlayerState。

旅行(Travel):从大厅到战局

TRAVEL_Absolute(去一个具体地址) vs TRAVEL_Relative(当前服务器内换地图) vs TRAVEL_Partial(部分加载):

// 客户端:去某个服务器
PC->ClientTravel(TEXT("127.0.0.1:7777"), TRAVEL_Absolute);
// 服务器:全员换地图(配合 seamless travel)
GetWorld()->ServerTravel(TEXT("/Game/Maps/Arena?a=1"));

无缝旅行(Seamless Travel) 是大厅→战局的关键:开启后服务器换地图时客户端不回主菜单、不断连接,直接流式加载新地图。要点:

  • bUseSeamlessTravel = true(GameMode)
  • 把需要保留的 Actor 标 bAlwaysRelevant 并在 GetSeamlessTravelActorList 里保留(如 PlayerController、PlayerState、规则数据)
  • 过渡地图(TransitionMap)可给玩家一个加载界面

详见「多人游戏中的旅行」(https://www.wanxiangyundang.top/read/unreal-engine-5-8-docs/travelling-in-multiplayer-in-u-54bf)。

退出流程

玩家退出                                       服务器
   │ ClientTravel 离开 / 点退出 / 断线
   │                            ←  Logout(PlayerController 销毁,PlayerState 标记销毁)
   │                            ←  保存数据、广播通知其他玩家、结算
   │                            ←  会话层 EndSession(如果最后一人则关服)

要点:

  • 数据保存在服务器权威侧:玩家退出时服务器主动存盘,别依赖客户端上报。
  • 掉线区分:超时(连接断了)与主动退出,数据保存策略一致,但可以在重连时给「断线补偿」。
  • PlayerState 的存活窗口:玩家断线后 PlayerState 保留一段时间再销毁(支持快速重连),由 GameMode 的 InactivePlayerState 机制管理。

加入失败的体感

加入失败(服务器满、版本旧、被 ban)要给明确反馈:

失败原因 给玩家的提示
服务器已满 「房间已满,正在返回匹配」
版本不匹配 「请更新到最新版本」
被 ban 「您被限制进入」(给申诉入口)
连接超时 「服务器无响应,正在重试(2/3)」

没有任何提示直接踢回主菜单是差体验的常见来源——而且玩家会怀疑「是不是我卡了」而不是「服务器的问题」。

心得:玩家生命周期这块「不出彩但出事就是大事」。我们的规范是:每个连接状态迁移(连接中/已连接/加载中/游戏中/掉线/重连)都在 GameMode 里有显式钩子+日志,线上问题 80% 靠这些日志定位。