主题
框架生命周期指南
本指南面向不看框架源码的游戏开发者,说明 WasiCore 从启动到结束的关键生命周期阶段,以及每个阶段适合做什么。
一张图看懂启动顺序
以下顺序基于当前框架真实执行流程:
text
1. OnRegisterGameClasses
2. 赋值 Game.GameModeLink
3. OnGameDataInitialization
4. 解析 / 校验当前 GameMode 数据
5. OnGameplaySettingsInitialization
6. OnGameSceneListInitialization
7. [CLIENT] CreateDefaultUI()
8. [CLIENT] OnGameUIInitialization
9. OnGameTriggerInitialization
10. OnGameInstanceInitialization
11. Initialized = true
12. 等待引擎启动、玩家/核心 Actor 就绪
13. OnGameStart / EventGameStart
14. OnGameEnd每个阶段该做什么
1. OnRegisterGameClass()
这是 IGameClass 的静态入口。框架会自动调用它,你不用也不能手动调用。
这个阶段只做一件事:订阅后续生命周期事件。
csharp
public class MyGameFeature : IGameClass
{
public static void OnRegisterGameClass()
{
Game.OnGameDataInitialization += OnGameDataInitialization;
#if CLIENT
Game.OnGameUIInitialization += OnGameUIInitialization;
#endif
Game.OnGameTriggerInitialization += OnGameTriggerInitialization;
Game.OnGameInstanceInitialization += OnGameInstanceInitialization;
}
}这个阶段不要做:
- 不要读取
Game.GameModeLink - 不要直接创建依赖当前游戏模式的数据
- 不要手动调用别的类的
OnRegisterGameClass()
2. Game.GameModeLink 赋值
所有 OnRegisterGameClass() 执行完之后,框架才会给 Game.GameModeLink 赋值。
这就是为什么游戏模式判断必须放到后续 handler 里,而不能放在 OnRegisterGameClass() 里。
3. OnGameDataInitialization
这是数据注册阶段。适合做:
- 创建
GameDataGameMode - 创建
GameDataUnit、GameDataAbility、GameDataScene等配置数据 - 给当前模式绑定
Gameplay、PlayerSettings、SceneList、DefaultScene
典型写法:
csharp
private static void OnGameDataInitialization()
{
if (Game.GameModeLink != ScopeData.GameDataGameMode.MapGameMode)
return;
_ = new GameDataGameMode(ScopeData.GameDataGameMode.MapGameMode)
{
Name = "MyMode",
Gameplay = GameCore.ScopeData.Gameplay.Default,
PlayerSettings = ScopeData.GameDataPlayerSettings.PlayerSettings,
SceneList = [ScopeData.GameDataScene.MyScene],
DefaultScene = ScopeData.GameDataScene.MyScene,
};
}4. OnGameplaySettingsInitialization
当前 GameMode 数据已经确定,可以在这里根据最终选中的 GameDataGameMode 调整玩法设置。
这个阶段通常用于:
- 读取最终
gameMode参数 - 初始化依赖
GameDataGameMode的全局玩法设置 - 框架级系统按模式做配置
5. OnGameSceneListInitialization
这是场景列表初始化阶段。大多数普通项目不需要直接处理它,但如果你有自定义场景列表装配逻辑,这里是合法时机。
6. [CLIENT] CreateDefaultUI() 与 OnGameUIInitialization
这是客户端 UI 初始化阶段。
顺序上,框架会先尝试创建 GameMode.GameUI 指向的默认 UI,然后触发 OnGameUIInitialization。
这个阶段适合做:
- 创建根 UI
- 创建 HUD、面板、按钮、Canvas
- 绑定输入
- 注册只依赖客户端 UI 的轻量逻辑
最重要的注意事项:
OnGameUIInitialization早于OnGameTriggerInitialization- 如果你在
OnGameTriggerInitialization里才去订阅Game.OnGameUIInitialization += ...,那已经太晚了,UI 初始化事件已经过去了
也就是说,UI 初始化 handler 必须在 OnRegisterGameClass() 阶段提前订阅
csharp
public static void OnRegisterGameClass()
{
#if CLIENT
Game.OnGameUIInitialization += OnGameUIInitialization;
#endif
Game.OnGameTriggerInitialization += OnGameTriggerInitialization;
}7. OnGameTriggerInitialization
这是运行时触发器 / 事件注册阶段。
适合做:
- 注册
Trigger<EventGameStart> - 注册 TypedMessage / Proto 消息处理器
- 注册运行时事件监听
- 注册
IThinker - 做需要
Game.Instance的事件挂接
典型写法:
csharp
private static void OnGameTriggerInitialization()
{
if (Game.GameModeLink != ScopeData.GameDataGameMode.MapGameMode)
return;
var trigger = new Trigger<EventGameStart>(OnGameStart);
trigger.Register(Game.Instance);
}8. OnGameInstanceInitialization
这是比 OnGameTriggerInitialization 更晚 的阶段。
如果你的逻辑依赖:
- 前面的触发器已经都注册完
- 当前
Game.Instance已经准备好 - 需要做更晚的实例级初始化
可以放在这里。
注意:旧文档里有些地方把它写在 OnGameTriggerInitialization 前面,这是不对的;实际顺序是先 Trigger,再 Instance。
9. OnGameStart
OnGameStart 不是“初始化一结束立刻触发”的事件。
框架还会等待这些条件满足后才真正开始游戏:
Initialized == true- 脚本已允许启动
- 玩家 Actor 已同步完成
- Game Property Actor 已就绪
只有这些条件都满足,才会触发:
Game.OnGameStartEventGameStart
因此:
- “注册逻辑”放在
OnGameTriggerInitialization - “真正开局时执行的逻辑”放在
OnGameStart/EventGameStart
10. OnGameEnd
这是脚本侧最后的清理窗口。适合做:
- 注销事件
- 清理 GameGraph / UI / 原生资源
- 结束后台循环
推荐分工
| 阶段 | 推荐职责 |
|---|---|
OnRegisterGameClass() | 只订阅生命周期事件 |
OnGameDataInitialization | 注册和创建 GameData |
OnGameUIInitialization | 创建客户端 UI |
OnGameTriggerInitialization | 注册触发器、消息、运行时事件 |
OnGameInstanceInitialization | 做更晚的实例级初始化 |
OnGameStart | 真正开始游戏逻辑 |
OnGameEnd | 清理资源 |
两个最常见的坑
坑 1:在 OnRegisterGameClass() 里读取 Game.GameModeLink
csharp
// ❌ 错误
public static void OnRegisterGameClass()
{
if (Game.GameModeLink != ScopeData.GameDataGameMode.MapGameMode)
return;
Game.OnGameTriggerInitialization += OnGameTriggerInitialization;
}正确写法:
csharp
// ✅ 正确
public static void OnRegisterGameClass()
{
Game.OnGameTriggerInitialization += OnGameTriggerInitialization;
}
private static void OnGameTriggerInitialization()
{
if (Game.GameModeLink != ScopeData.GameDataGameMode.MapGameMode)
return;
}坑 2:在 OnGameTriggerInitialization 里才订阅 OnGameUIInitialization
csharp
// ❌ 错误:已经错过 UI 初始化时机
private static void OnGameTriggerInitialization()
{
Game.OnGameUIInitialization += OnGameUIInitialization;
}正确写法:
csharp
// ✅ 正确:提前订阅
public static void OnRegisterGameClass()
{
#if CLIENT
Game.OnGameUIInitialization += OnGameUIInitialization;
#endif
}相关阅读
guides/QuickStart.md- 框架约束与排错入口
best-practices/CommonPitfalls.mdSimple2DMultiplayer/Framework.md