Skip to content

框架生命周期指南 ​

本指南面向不看框架源码的游戏开发者,说明 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()

所有 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.OnGameStart
  • EventGameStart

因此:

  • “注册逻辑”放在 OnGameTriggerInitialization
  • “真正开局时执行的逻辑”放在 OnGameStart / EventGameStart

10. OnGameEnd ​

这是脚本侧最后的清理窗口。适合做:

  • 注销事件
  • 清理 GameGraph / UI / 原生资源
  • 结束后台循环

推荐分工 ​

阶段推荐职责
OnRegisterGameClass()只订阅生命周期事件
OnGameDataInitialization注册和创建 GameData
OnGameUIInitialization创建客户端 UI
OnGameTriggerInitialization注册触发器、消息、运行时事件
OnGameInstanceInitialization做更晚的实例级初始化
OnGameStart真正开始游戏逻辑
OnGameEnd清理资源

两个最常见的坑 ​

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
}

相关阅读 ​