主题
常驻游戏局
系统文档: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 应明确提示这一副作用,不得把它作为正常升级方案。
架构检查
在生成或审查代码时确认:
- 是否由作者创建目标房间,并通过服务端可信的创建者
UserId、房间参数或项目条件识别,而不是让所有游戏局自动申请。 - 是否明确拒绝在
debug环境验收,并安排至少test环境测试。 - 是否在首次申请常驻前已经具备状态查询、排空、主动关闭和鉴权入口。
- 是否只在
Success后启动长期业务。 - 是否错误假设申请成功意味着全项目唯一实例。
- CloudData 是否等待 ready,并使用
User.UserId。 - ServerChannel 业务消息、管理命令和结算是否具备幂等性。
- 发布新版时是否能让旧常驻局主动退出,再由新版本接管。
- Host 故障或平台终止后,业务是否能从持久化状态恢复。
相关 Skill
- 云数据读写、ready gate 和错误处理:
cloud-data。 - 跨游戏局消息传递:阅读
docs/systems/ServerChannelSystem.md。 - 服务端运行日志与行为定位:
behavior-troubleshoot。