You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity(C#)游戏状态更新:Switch Case与事件实现方案对比

选择事件通知还是Switch Case来处理Unity游戏状态变更?

这是Unity项目里很常见的设计抉择,我来结合两种方案的实际使用场景给你唠唠:

先说说Switch Case的路子

你提到的Switch Case实现,大概是像这样的:

public static GameState currentGameState;

public static void SetGameState(GameState newState)
{
    currentGameState = newState;
    switch(newState)
    {
        case GameState.Intro:
            GUIManager.Instance.ShowIntroUI();
            SoundsManager.Instance.PlayIntroMusic();
            CameraManager.Instance.ZoomToIntroView();
            // 其他管理器的操作...
            break;
        case GameState.Tutorial:
            GUIManager.Instance.ShowTutorialUI();
            InputsManager.Instance.LockMovement();
            TerrainManager.Instance.LoadTutorialTerrain();
            // 其他操作...
            break;
        case GameState.Gameplay:
            // 对应各个管理器的初始化操作
            break;
    }
}

它的优点:

  • 直观好上手:所有状态变更的逻辑都集中在GameManager的一个方法里,刚接手项目的人一眼就能看明白每个状态下各个管理器做了什么,调试的时候也不用跳来跳去。
  • 初期开发快:不用额外搭事件框架,直接写case调用就行,适合小体量的项目。

但缺点也很明显:

  • 耦合度拉满:GameManager必须知道所有其他管理器的存在,每次加个新的管理器(比如以后加个AchievementManager),或者加个新的游戏状态(比如MiniGame),你都得回到这个switch里加代码,违反了开闭原则——对扩展开放,对修改关闭。
  • 代码会越来越臃肿:随着项目变大,状态和管理器增多,这个switch case会变得超长,维护起来特别头疼,找个状态的逻辑都要翻半天。

再聊聊事件通知的方案

这种方案是让GameManager只负责触发状态变更事件,各个管理器自己订阅这个事件,处理自己的逻辑。举个例子:

首先在GameManager里定义事件:

public static event Action<GameState> OnGameStateChanged;
public static GameState currentGameState;

public static void SetGameState(GameState newState)
{
    currentGameState = newState;
    // 触发事件,通知所有订阅者
    OnGameStateChanged?.Invoke(newState);
}

然后每个管理器自己订阅并处理:

// 比如GUIManager.cs
private void Awake()
{
    // 订阅事件
    GameManager.OnGameStateChanged += HandleGameStateChanged;
}

private void HandleGameStateChanged(GameState newState)
{
    switch(newState)
    {
        case GameState.Intro:
            ShowIntroUI();
            break;
        case GameState.Tutorial:
            ShowTutorialUI();
            break;
        case GameState.Gameplay:
            ShowHUD();
            break;
    }
}

// 一定要记得取消订阅,避免内存泄漏
private void OnDestroy()
{
    GameManager.OnGameStateChanged -= HandleGameStateChanged;
}

其他管理器(比如SoundsManager、CameraManager)也是类似的逻辑,各自处理自己的状态响应。

它的优点:

  • 低耦合:GameManager完全不用知道有哪些管理器存在,只需要管好状态和触发事件就行。加新管理器或者新状态时,只需要在对应的管理器里加处理逻辑,不用动GameManager的代码,完美符合开闭原则。
  • 职责清晰:每个管理器只处理和自己相关的状态逻辑,不会出现GameManager变成什么都管的“上帝类”。

小缺点:

  • 初期需要搭框架:比起直接写switch,要多写一些事件订阅/取消的代码,对新手来说可能有点门槛。
  • 逻辑分散:状态变更的整体流程不再集中在一个地方,调试时可能需要跳转到各个管理器的处理方法,不过习惯了之后其实还好,而且可以通过命名规范(比如统一用HandleGameStateChanged作为方法名)来快速定位。

给你的实际建议

  • 如果你的项目很小:比如只有3-4个游戏状态,管理器也不多(5个以内),Switch Case完全够用,简单直接,没必要搞复杂的事件。
  • 如果你的项目有扩展计划:比如以后要加新的状态、新的玩法模块,或者团队协作开发,强烈推荐用事件通知的方案。它能让你的代码结构更健壮,后期维护成本低很多,也不容易因为改GameManager的代码引入bug。
  • 也可以灵活结合:比如一些核心的、必须保证同步执行的操作,在GameManager里用少量switch处理,其他非核心的交给事件,但尽量保持代码风格一致,别混合得太乱。

另外,Unity里还可以用ScriptableObject来做事件载体,这种方式更灵活,甚至能在编辑器里配置响应逻辑,但如果你的管理器都是单例,用静态事件就完全够用了。

内容的提问来源于stack exchange,提问作者Ashlanfox

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 04:11:36