跨服指来自不同游戏服的玩家进入同一个逻辑空间进行交互例如跨服战场、跨服组队副本、跨服竞技场、跨服拍卖行、跨服世界 BOSS 等。跨服的主要复杂度在服务端但客户端同样需要做不少工作连接切换、身份携带、数据隔离、状态管理、断线容错。下面从架构到细节逐层拆解。一、先打个比方出国旅行现实游戏跨服本国原服Home Server国外跨服服务器Cross Server护照 签证跨服令牌Cross Ticket海关跨服鉴权出国只能带随身行李只携带角色快照战力、装备、外观房子、存款留在国内背包、仓库、货币仍归原服管理姓名前加国籍玩家名显示为[S102] 张三回国后结算跨服奖励回原服发放客户端就是这位旅行者要知道自己现在在哪、该找谁办事、行李里什么能用以及签证过期了怎么办。二、三种主流接入架构架构 A网关透明转发客户端最简单客户端 ──(长连接不变)── 网关 ──┬── 原服逻辑 └── 跨服逻辑网关按路由转发客户端连接始终不断只是网关把部分消息转发到跨服客户端只需知道当前处于跨服状态协议可能带路由标记优点无需断线重连体验平滑缺点网关压力大跨机房延迟会叠加。架构 B客户端直连切换客户端 ──X── 原服断开或保持心跳 └──────── 跨服服务器新建连接凭令牌登录原服下发跨服地址和令牌客户端主动连接跨服优点链路短、延迟低适合实时战斗缺点客户端需要处理连接切换、登录、失败回退等复杂逻辑。架构 C双连接并存客户端 ══ 原服连接聊天、邮件、背包、充值 ══ 跨服连接战斗、场景同步跨服期间仍能收到原服的私聊、邮件、充值到账通知优点功能完整回原服无需重新登录缺点需要管理两条连接的心跳、重连和消息路由。维度A 网关转发B 直连切换C 双连接客户端复杂度低中高战斗延迟较高低低跨服时原服功能可用不可用可用典型场景MMO 跨服活动MOBA/竞技对战大型 MMO、SLG三、客户端核心模块设计1. 连接管理器多通道 消息路由publicenumChannelType{Home,Cross}publicclassNetManager{privatereadonlyDictionaryChannelType,NetChannel_channelsnew();// 根据协议号决定走哪条通道publicvoidSend(IMessagemsg){varchannelRouteTable.GetChannel(msg.MsgId,CrossContext.IsInCross);_channels[channel].Send(msg);}publicasyncTaskboolConnectCross(stringhost,intport,CrossTicketticket){varchnewNetChannel(ChannelType.Cross);if(!awaitch.Connect(host,port,timeoutMs:5000))returnfalse;varrespawaitch.RequestCrossLoginResp(newCrossLoginReq{Ticketticket});if(resp.Code!0){ch.Close();returnfalse;}_channels[ChannelType.Cross]ch;returntrue;}}路由表示例协议模块普通状态跨服状态移动 / 技能 / 战斗HomeCross跨服聊天频道—Cross私聊 / 邮件 / 好友HomeHome背包 / 充值 / 商城HomeHome或禁用组队HomeCross2. 跨服状态机最核心的部分跨服流程本质上是一个状态机所有异常都要有明确的出口┌──────────┐ 报名/匹配 ┌──────────┐ 匹配成功 │ Normal │────────────▶│ Matching │──────────┐ └──────────┘◀────────────└──────────┘ ▼ ▲ 取消/超时 ┌─────────────┐ │ │ Transferring│ 获取令牌、连接、登录、加载场景 │ └─────────────┘ │ 失败/超时 ◀──┘ │ 成功 │ ▼ ┌───────────┐ 活动结束/主动退出 ┌──────────┐ │ Returning │◀────────────────────────────│ InCross │ └───────────┘ 跨服宕机/被踢 └──────────┘ │ │ 断线 │ ▼ │ ┌─────────────┐ └────────── 重连失败 ◀────────────│Reconnecting │ └─────────────┘publicenumCrossState{Normal,Matching,Transferring,InCross,Reconnecting,Returning}publicclassCrossStateMachine{publicCrossStateState{get;privateset;}publicvoidChangeState(CrossStatenext){if(!IsValidTransition(State,next)){Log.Error($非法跨服状态切换:{State}-{next});return;}varprevState;Statenext;EventBus.Publish(newCrossStateChanged(prev,next));// UI、音效、功能开关监听}} 经验不要用一堆 bool 标记isInCross、isTransferring……拼凑状态这样迟早会出现既在跨服又不在跨服的诡异 Bug。3. 跨服令牌客户端的护照客户端不能自己证明身份必须由原服签发令牌CrossTicket { accountId // 账号 ID roleId // 角色 ID homeServerId // 原服 ID crossServerId // 目标跨服 ID activityId // 本次活动/房间 expireTime // 过期时间通常 30~60 秒 signature // 原服用密钥签名客户端无法伪造 }客户端注意事项令牌只透传不解析不缓存到磁盘令牌过期后要回原服重新申请而不是反复重试旧令牌重连时一般使用跨服下发的重连令牌而不是最初的进入令牌。4. 数据上下文隔离分清国内资产和随身行李这是客户端最容易出 Bug 的地方。建议显式拆分两套数据publicclassPlayerDataContext{publicHomePlayerDataHome;// 原服完整数据背包、货币、任务、公会……publicCrossPlayerDataCross;// 跨服数据快照属性、临时积分、阵营、跨服 Buff// 当前生效的战斗属性publicBattleAttrCurrentAttrCrossContext.IsInCross?Cross.Attr:Home.Attr;}常见原则数据跨服期间的处理战力 / 属性使用进入时的快照期间换装可能不生效背包 / 货币只读显示或禁止操作跨服积分 / 临时道具存在 Cross 上下文离开时清空任务进度跨服内产生的进度通过原服同步回来奖励通常由跨服通知原服原服通过邮件或背包推送发放回原服时务必清理跨服数据否则会出现回城后头顶还挂着跨服阵营标识之类的残留问题。5. 全局唯一标识解决重名和ID 冲突单服时roleId 10086是唯一的但跨服后S1 和 S2 都可能有 10086。解决方案// 方式一复合 IDpublicstructGlobalRoleId{publicintServerId;publiclongRoleId;}// 方式二位运算打包成一个 longlongglobalId((long)serverId40)|localRoleId;客户端需要全面排查的地方以roleId作为 Key 的字典玩家实体缓存、头像缓存、组队列表本地存储聊天记录、屏蔽列表名字显示[S102]张三或张三·青龙服公会、队伍名称同样可能重名点击头像查看信息时要带上serverId去请求。6. 进入跨服的完整时序客户端 原服 跨服中心/匹配 跨服战斗服 │ 报名请求 │ │ │ │───────────────▶│ 转发报名 │ │ │ │───────────────────▶│ │ │ 匹配中... │ │ 匹配成功分配房间 │ │ │◀───────────────────│───────────────────▶│ 预创建房间 │ 匹配成功令牌地址│ │ │ │◀───────────────│ 上传角色快照 ──────────────────────────▶│ │ │ │ ① 预加载场景资源可与连接并行 │ │ ② 连接跨服 令牌登录 ──────────────────────────────────▶│ │◀───────────────────────────────── 登录成功 场景初始数据 │ │ ③ 切换场景、创建实体 │ │ ④ 发送加载完成 ──────────────────────────────────────▶│ │◀─────────────────────────────────────── 开始同步战斗 │体验优化技巧匹配成功后立即预加载地图资源与网络连接并行用 Loading 界面掩盖连接耗时显示双方阵营信息服务端应等待所有玩家加载完成或超时再开战避免加载慢的玩家一进场就挨打。7. 断线重连跨服最容易翻车的地方跨服场景中的断线情况比单服复杂得多场景客户端处理网络闪断跨服房间仍在用重连令牌直连跨服拉取全量快照恢复场景重连时活动已结束跨服返回房间不存在转为 Returning回原服并展示结算跨服服务器宕机多次重连失败后回原服提示跨服异常奖励将通过邮件补发App 被杀后重新登录登录原服时原服告知你有未完成的跨服对局询问是否重新进入原服连接也断了双连接架构优先恢复原服连接再决定是否回跨服asyncTaskHandleCrossDisconnect(){sm.ChangeState(CrossState.Reconnecting);for(inti0;i3;i){varresultawaitnet.ReconnectCross(CrossContext.ReconnectTicket);switch(result){caseReconnectResult.Success:awaitSceneSync.ApplyFullSnapshot();// 拉全量数据不要依赖断线前状态sm.ChangeState(CrossState.InCross);return;caseReconnectResult.RoomClosed:gotoReturnHome;// 活动已结束直接回原服}awaitTask.Delay(1000*(i1));// 退避重试}ReturnHome:sm.ChangeState(CrossState.Returning);awaitReturnToHomeServer();}⚠️ 关键重连成功后一定要拉取全量状态客户端不能假设断线期间什么都没发生。8. 时间与配置差异不同服的开服时间不同导致一些隐蔽问题服务器时间跨服期间所有倒计时活动结束、技能 CD、Buff 时长都应以跨服时间为准需要单独做一次时间同步开服天数相关逻辑原服第 30 天和第 300 天的玩家在一起开服 N 天解锁类功能要以跨服规则判定配置版本不同服如果灰度了不同版本的配置表跨服时要校验版本号必要时拒绝进入并提示更新客户端版本跨服登录时上报客户端版本协议不兼容直接拦截。9. 社交与聊天聊天频道 跨服期间路由 ───────────────────────────────── 世界频道 → 原服或屏蔽 跨服频道 → 跨服服务器 战场/阵营频道 → 跨服战斗服 私聊 → 原服通过中心服转发给其他服玩家 公会 → 原服注意点跨服玩家互加好友需要服务端支持跨服社交中心客户端好友列表要支持显示不同服的玩家屏蔽列表要按GlobalRoleId存储跨服中查看别人的详细信息可能需要异步请求对方原服UI 要能处理加载中和失败状态。10. UI 与功能开关跨服状态下很多功能需要禁用或改变表现// 每个功能入口声明跨服可用性统一由功能开关系统管理[FeatureEntry(id:Shop,allowInCross:false,tip:跨服期间无法使用商城)][FeatureEntry(id:Bag,allowInCross:true,readOnly:true)][FeatureEntry(id:Mail,allowInCross:true)]主界面顶部显示跨服标识及当前所在战区禁用的按钮置灰并提示原因而不是点了没反应跨服内的红点、提示不要与原服逻辑混在一起退出跨服后统一刷新一次所有功能入口的状态。11. 本地缓存命名空间客户端本地缓存PlayerPrefs、SQLite、文件同样需要隔离错误 cache/chat_history.db 正确 cache/{accountId}/{serverId}/chat_history.db cache/{accountId}/cross/{activityId}/battle_log.db否则会出现切服或跨服后看到其他服聊天记录的问题。四、常见坑清单坑表现解决思路状态用 bool 拼凑卡在半跨服状态界面错乱统一状态机状态切换集中管理ID 未带服务器号不同服同 ID 玩家头像、名字串号全面改用 GlobalRoleId跨服数据未清理回城后仍显示跨服 Buff、阵营标识Returning 状态统一清理 Cross 上下文消息乱序切换期间原服旧消息覆盖跨服状态消息带会话序号丢弃过期会话消息场景加载慢进场即被击杀加载完成确认 进场无敌保护令牌重复使用重连失败或安全漏洞令牌一次性 独立重连令牌时间不同步倒计时与服务器不一致跨服单独做时间同步奖励未到账跨服宕机导致结算丢失服务端保证最终一致客户端只负责展示回原服失败玩家卡在 Loading回原服失败时走完整重新登录流程兜底跨服中充值到账通知收不到双连接或回原服后补推通知关于消息乱序推荐引入会话纪元Session Epoch机制// 每次进入或离开跨服纪元 1处理消息时丢弃旧纪元的消息voidOnMessage(NetMessagemsg){if(msg.EpochCrossContext.CurrentEpoch)return;// 过期消息直接丢弃Dispatcher.Dispatch(msg);}五、测试与调试建议GM 命令一键进入跨服、强制断开跨服、模拟跨服宕机、修改跨服时间弱网模拟在传送、加载、结算等关键时刻注入丢包和延迟异常时机测试在状态机的每个状态中切后台、杀进程、断网验证都能恢复到合法状态多服混测至少用 3 个不同开服时间、不同配置版本的服进行联调日志埋点每次状态切换记录traceId客户端日志与服务端日志可以串联排查可视化面板开发版显示当前状态、连接情况、Epoch、所在跨服节点 ID。六、总结客户端跨服逻辑可以归纳为五个关键词状态机跨服是一段有明确起点和终点的流程每个异常都要有出口身份令牌由服务器签发ID 全局唯一显示时带上服务器标识隔离原服数据与跨服数据分开存放离开时彻底清理路由消息知道自己该发往哪里旧会话的消息坚决丢弃兜底任何失败都能回到原服奖励交给服务端保证最终一致。一句话概括客户端是一个持证出国的旅行者签证由国内签发行李只带必需品任何意外都要保证能平安回家。
阅读完成 · 觉得有帮助?