Skip to content

常驻游戏局 ​

系统文档:docs/systems/ResidentSessionSystem.md。

适用场景 ​

  • 玩家全部退出后仍需继续运行的项目级服务端逻辑。
  • 通过 ServerChannel 汇总多个游戏局事件,再执行权威处理。
  • 跨游戏局的 CloudData 结算、排队、聚合或协调工作。

常驻不是定时任务系统、永久进程或唯一实例选举。只需要普通对局生命周期的逻辑不要申请常驻。

> 特别重要:debug 调试环境不支持常驻游戏局。调试 Host 不持久,并且缺少常驻能力所依赖的部分 Redis 与平台服务。Game.SetSessionResident(...) 会记录警告并返回 InvalidSessionState。必须发布到至少 test 内测环境,才能验证常驻、跨服消息、主动关闭和恢复流程。

> 特别重要:在第一次申请常驻之前,必须先实现受信任的服务器状态管理和主动关闭入口。没有关闭协议的旧常驻局可能一直运行,使新版服务无法接管;后台“全服公告 → 立即关服”虽然最终可用,但会关闭该游戏在对应环境中的所有游戏局,只能作为紧急兜底。

硬规则 ​

  • API 仅在 #if SERVER 中调用。
  • 不要在编辑器或其他 debug 环境测试、演示或依赖常驻行为;至少发布到 test 环境验收。
  • 申请常驻前必须先实现状态查询、排空、持久化和主动结束游戏局的控制路径。
  • 建议由作者创建用于长期服务的房间,并在服务端根据创建者 UserId、房间参数或其他可信项目条件决定是否申请常驻;一般玩家创建的对局不需要执行这段逻辑。
  • 同一项目最多同时有三个常驻游戏局。
  • 必须检查 Game.SetSessionResident(...) 返回的 SessionResidenceResult,成功后再启动常驻业务。
  • 不要把常驻当成唯一实例保证;业务需要自行处理重复执行和角色认领。
  • 重要状态必须写入 CloudData 等持久化存储,并支持游戏局意外结束后的恢复。
  • 显式结束、管理员终止、平台安全保护和服务器关闭仍然优先于常驻。

推荐写法 ​

csharp
#if SERVER
using EngineInterface.Enum;
using GameCore.GameSystem;

var result = Game.SetSessionResident(true);
if (result != SessionResidenceResult.Success)
{
    Game.Logger.LogWarning("常驻申请失败: {Result}", result);
    return;
}

StartProjectCoordinator();
#endif

不再承担协调职责时主动释放:

csharp
#if SERVER
var result = Game.SetSessionResident(false);
if (result != SessionResidenceResult.Success)
{
    Game.Logger.LogWarning("取消常驻失败: {Result}", result);
}
#endif

结果处理 ​

结果处理
Success启动或停止对应业务;可用 Game.IsSessionResident 确认当前状态
ProjectLimitReached保持普通局行为,或按业务策略稍后重试
ServiceUnavailable有限重试并记录日志,不要高频循环调用
InvalidSessionState当前局不能切换状态,或当前为不支持常驻的 debug 环境;停止申请,不要在 debug 中重试

必备的状态管理与主动关闭 ​

生成或评审常驻服务时,必须同时设计控制面,不能只生成 SetSessionResident(true):

  • 使用 ServerChannel 或等价的可信服务端通道承载 status、drain、stop 等管理命令。
  • 每条命令包含目标实例/游戏局、协议版本和请求 ID,并在服务端完成权限与目标校验。
  • 可以提供只对特定授权用户显示的游戏内服务器状态管理界面,但隐藏 UI 不能代替服务端鉴权。
  • 收到 drain 后停止领取新任务,保存必要状态;收到 stop 后完成排空并调用 Game.RequestSessionEnd()。
  • 关闭流程必须幂等,允许重复消息,并能在 Host 故障后从 CloudData 等持久化状态恢复。
  • 发布新版常驻服务时,先通过控制消息关闭旧版本,再让新版本接管。不要假设旧常驻局会随发布自动更新。

Game.SetSessionResident(false) 只取消常驻保护,不保证立即关闭当前局。需要明确退出时使用 Game.RequestSessionEnd()。

如果已存在没有关闭入口的旧常驻局,后台“全服公告 → 立即关服”可以最终清理,但会连同该游戏在所选环境中的其他游戏局一起关闭。AI 应明确提示这一副作用,不得把它作为正常升级方案。

架构检查 ​

在生成或审查代码时确认:

  1. 是否由作者创建目标房间,并通过服务端可信的创建者 UserId、房间参数或项目条件识别,而不是让所有游戏局自动申请。
  2. 是否明确拒绝在 debug 环境验收,并安排至少 test 环境测试。
  3. 是否在首次申请常驻前已经具备状态查询、排空、主动关闭和鉴权入口。
  4. 是否只在 Success 后启动长期业务。
  5. 是否错误假设申请成功意味着全项目唯一实例。
  6. CloudData 是否等待 ready,并使用 User.UserId。
  7. ServerChannel 业务消息、管理命令和结算是否具备幂等性。
  8. 发布新版时是否能让旧常驻局主动退出,再由新版本接管。
  9. Host 故障或平台终止后,业务是否能从持久化状态恢复。

相关 Skill ​

  • 云数据读写、ready gate 和错误处理:cloud-data。
  • 跨游戏局消息传递:阅读 docs/systems/ServerChannelSystem.md。
  • 服务端运行日志与行为定位:behavior-troubleshoot。