我们来用Unity的形式来讲解一下状态模式。
 
你可以把状态模式想象成一个”角色行为控制器”. 一个对象(比如游戏角色)在不同的情况下会有不同的行为表现, 这些不同的情况就是它的”状态”. 状态模式的核心思想是: 将对象的每种状态封装成独立的类, 当对象的状态发生改变时, 它的行为也会随之改变, 就好像这个对象本身发生了变化一样.
 

举个具体场景: 游戏角色的状态管理

假设你正在开发一个动作游戏, 玩家角色(Player)有几种状态:
 
  • 空闲状态(IdleState): 角色站立不动, 不妨空闲动画.
  • 移动状态(MoveState): 角色根据输入方向移动, 播放移动动画.
  • 跳跃状态(JumpState): 角色向上跳起, 播放跳跃动画, 期间不能移动或再次跳跃.
  • 攻击状态(AttackState): 角色执行攻击动作, 播放攻击动画, 期间不能移动或跳跃.
 
如果不使用状态模式, 你可能会在Player 脚本中使用大量的 if-elseswitch 语句来判断当前状态, 然后执行相应的逻辑. 这会导致 Update 方法变得非常臃肿 \ 难以维护和扩展.
这种写法的问题很明显:
  • 代码臃肿: 所有状态的逻辑都混在一个 Update 方法里.
  • 耦合度高: 状态之间的转换逻辑和状态本身的行为逻辑交织在一起.
  • 难以扩展: 新增一个状态(如 ”受伤”)需要修改大量现有代码, 容易引入bug.
 

状态模式如何解决这个问题?

状态模式将每个状态的行为和转换逻辑封装到独立的类中.
  1. 定义一个抽象的接口(IPlayerState), 所有具体状态都要实现它. 这个接口通常包含 EnterState() \ UpdateState()ExitState() 等方法
  1. 为每个具体状态创建一个类(如 IdleState \ MoveState ), 它们实现 IPlayerState 接口, 并在相应的方法中实现该状态下的行为和状态转换的逻辑.
  1. 在角色控制器(PlayerController )中, 持有一个当前状态的引用. 它不在包含具体的状态逻辑, 而是将 Update 等调用委托给当前状态对象. 当需要切换状态时, 它会调用当前状态的 ExitState() , 然后切换到新状态并调用其 EnterState() .
 

代码实现步骤

  1. 定义抽象状态接口(IPlayerState.cs)
 
  1. 实现具体状态类
空闲状态(IdleState.cs)
 
移动状态 (MoveState.cs)
 
跳跃状态 (JumpState.cs)
 
攻击状态 (AttackState.cs)
 
  1. 实现上下文(Context)类(PlayerController.cs )
这个类是状态模式的”大脑”, 它持有所有状态的实例, 并负责状态的切换.
 
在Unity编译器中配置
  1. 创建一个玩家对象, 并添加 PlayerController 脚本.
  1. 为玩家对象添加 Animator\Rigidbody2DCollider2D 组件.
  1. 创建一个动画控制器(AnimatorController), 并设置好 Idle\Move\Jump\Attack等动画状态和参数(Trigger)
  1. 在 PlayerController的Inspector面板中, 将Animator\Rigidbody2DgroundCheck (一个用于检测地面的空对象)拖入到对应字段
  1. 运行游戏, 你可以通过WASD或方向键移动, 空格键跳跃, 鼠标左键攻击, 角色会在不同的状态间正确切换.
 

状态模式的核心优势

  1. 封装性: 每个状态的行为和转换逻辑都被封装在独立的类中, 是的代码结构清晰, 易于理解和维护.
  1. 可读性: 通过类名(如 IdeleState )就能直观地僚机额对象在该状态下的行为.
  1. 可扩展性: 新增一个状态(如”受伤”\”防御”)非常简单, 只需要创建要给新的状态类并实现相应接口, 几乎不需要修改现有代码, 符合”开放 - 封闭原则”.
  1. 消除复杂条件判断: 彻底告别了冗长的 if-elseswitch 语句, 将状态转换的决策分散到各个状态中.
  1. 状态独立: 各个状态类之间低耦合, 它们只通过 PlayerController 进行通信.
 

在 Unity中的其他应用场景

  • 敌人AI: 敌人可以有”巡逻”\”追击”\”攻击”\”逃跑”\”死亡”等状态.
  • UI界面管理: 一个复杂的UI面板可以有”正常”\”编辑”\”锁定”等状态, 每种状态下按钮的交互逻辑不同.
  • 游戏流程管理: 游戏可以有”主菜单”\”游戏进行中”\”暂停”\”游戏结束”等状态.
 
总结: 状态模式是一种非常强大的设计模式, 特别适合用于那些对象行为随状态改变而比那花的场景. 它通过将状态封装成独立的对象, 让代码变得更加优雅\可维护和可扩展. 在游戏开发中, 尤其是角色控制器和AI行为的设计中, 状态模式是不可或缺的工具.