如何解决游戏开发中传统State模式的局限性?
解决传统状态模式在游戏开发中的局限性
我在游戏开发中实现了状态模式,比如玩家拥有Idle、Run、Attack等多种状态,每个状态都用独立类实现,且由状态自身负责状态转换逻辑(例如Idle状态可直接转换至Attack状态,而Jump状态需要等玩家落地后才能转换至Idle状态)。以下是最初的实现思路:
class Player { private State _state = null; public Player() { this.TransitionTo(new IdleState(this)); } public void TransitionTo(State state) { this._state = state; this._state.SetPlayer(this); } public void Jump() { this._state.jump(); } } abstract class State { protected Player _player; public void SetPlayer(Player player) { this._player = player; } public abstract void Jump(); } class JumpState : State { public override void Jump() { // 不允许二段跳 } } class IdleState : State { public override void Jump() { this._player.TransitionTo(new JumpState()); } }
这个实现能正常运行,但存在两大局限性:
- 无法灵活替换特定状态实现:比如有的敌人跳跃时可受伤害,有的不可。虽然可以通过
override修改Jump状态的行为,但当前实现中状态转换时直接依赖具体状态类(比如IdleState硬编码转换至JumpState),若要换成JumpNoDamageState,就得额外创建对应的IdleNoDamageState,导致类爆炸。 - 状态与特定角色紧耦合:比如两个敌人基础行为完全一致,仅当生命值低于10%时其中一个会触发
Escape状态。按当前实现,必须为这个敌人重新创建所有状态类,因为每个状态都需要知晓新的转换规则和目标状态。
解决方案
核心思路是通过解耦状态与实例创建、解耦状态与具体角色类型来解决这些问题:
1. 将状态实例的创建逻辑从状态类中剥离
让角色(Player/Enemy)负责管理状态实例的创建和存储,状态类只通过角色获取目标状态,而非直接new具体类。这样替换状态实现时,只需要修改角色的状态初始化逻辑,无需改动状态类本身。
示例修改:
// 定义抽象角色接口 public interface ICharacter { void TransitionTo(IState state); T GetState<T>() where T : IState; bool IsGrounded { get; } int Health { get; } } // 抽象状态接口 public interface IState { void SetCharacter(ICharacter character); void Jump(); void Update(); } public abstract class BaseState : IState { protected ICharacter _character; public void SetCharacter(ICharacter character) { _character = character; } public abstract void Jump(); public virtual void Update() { } } // 修改IdleState,不再硬编码创建JumpState public class IdleState : BaseState { public override void Jump() { // 从角色处获取Jump状态实例 _character.TransitionTo(_character.GetState<JumpState>()); } } // 角色类负责管理状态实例 public class Player : ICharacter { private IState _currentState; private readonly Dictionary<Type, IState> _states = new(); public Player() { // 初始化状态,可随时替换为不同实现 _states.Add(typeof(IdleState), new IdleState()); // 若需要无伤害跳跃,只需替换这里的状态实例 // _states.Add(typeof(JumpState), new JumpNoDamageState()); _states.Add(typeof(JumpState), new JumpState()); TransitionTo(GetState<IdleState>()); } public void TransitionTo(IState state) { _currentState = state; _currentState.SetCharacter(this); } public T GetState<T>() where T : IState { return _states[typeof(T)] as T; } public bool IsGrounded { get; private set; } public int Health { get; private set; } public void Jump() { _currentState.Jump(); } public void Update() { _currentState.Update(); } }
2. 让状态依赖抽象角色,分离转换规则与状态逻辑
让状态类依赖抽象的ICharacter接口而非具体的角色类,同时把状态转换的条件判断(比如生命值低于10%转Escape)从状态类中移到角色类或专门的规则类中,让状态类只专注于当前状态的行为逻辑。
示例扩展:
// 新增Escape状态 public class EscapeState : BaseState { public override void Jump() { // 逃跑状态下的跳跃逻辑 } public override void Update() { // 逃跑状态的帧更新逻辑 } } // 带逃跑逻辑的敌人 public class EnemyWithEscape : ICharacter { private IState _currentState; private readonly Dictionary<Type, IState> _states = new(); public EnemyWithEscape() { // 复用通用状态类 _states.Add(typeof(IdleState), new IdleState()); _states.Add(typeof(AttackState), new AttackState()); _states.Add(typeof(JumpState), new JumpState()); _states.Add(typeof(EscapeState), new EscapeState()); TransitionTo(GetState<IdleState>()); } // 实现ICharacter接口的其他方法... public void Update() { _currentState.Update(); // 在角色层处理转换规则,状态类无需知晓 if (Health < 10 && _currentState is not EscapeState) { TransitionTo(GetState<EscapeState>()); } } } // 普通敌人,无需逃跑状态 public class RegularEnemy : ICharacter { private IState _currentState; private readonly Dictionary<Type, IState> _states = new(); public RegularEnemy() { // 复用和EnemyWithEscape相同的通用状态类 _states.Add(typeof(IdleState), new IdleState()); _states.Add(typeof(AttackState), new AttackState()); _states.Add(typeof(JumpState), new JumpState()); TransitionTo(GetState<IdleState>()); } // 实现ICharacter接口的其他方法... public void Update() { _currentState.Update(); // 无逃跑转换逻辑 } }
总结
通过以上两点修改,状态类不再依赖具体的状态实现和角色类型,角色可以灵活替换状态实例、自定义转换规则,避免了类爆炸和紧耦合的问题,让状态模式在游戏开发中更具扩展性。
内容的提问来源于stack exchange,提问作者Victor
相关产品推荐
相关产品推荐

