Unity可复用状态机泛型抽象类及构造器问题排查与重构
问题描述
我正尝试在Unity中实现一款支持普通状态与层级状态的可复用状态机,定义了BaseState、StateMachine、StateFactory三个核心抽象类。
BaseState
public abstract class BaseState<EState> where EState : Enum { protected StateFactory<EState, BaseState<EState>> _factory; protected StateMachine<EState, BaseState<EState>> _machine; protected EState _stateKey; public BaseState(EState stateKey, StateMachine<EState, BaseState<EState>> machine, StateFactory<EState, BaseState<EState>> factory) { _stateKey = stateKey; _machine = machine; _factory = factory; } //无关逻辑 }
HierarchicalBaseState
public abstract class HBaseState<EState> : BaseState<EState> where EState : Enum { //是否为根状态 protected bool _isRootState = false; //当前状态的父状态与子状态引用 protected HBaseState<EState> _parentState; protected HBaseState<EState> _childState; public HBaseState(EState stateKey, StateMachine<EState, HBaseState<EState>> machine, StateFactory<EState, HBaseState<EState>> factory, bool isRootState = false) : base(stateKey, machine, factory) { _stateKey = stateKey; _isRootState = isRootState; } //无关逻辑 }
StateMachine
public abstract class StateMachine<EState, StateType> : MonoBehaviour where EState : Enum where StateType : BaseState<EState> { protected StateFactory<EState, StateType> _factory; public StateType _currentState; //无关逻辑 }
StateFactory
public abstract class StateFactory<EState, StateType> : MonoBehaviour where EState : Enum where StateType : BaseState<EState> { protected StateMachine<EState, StateType> _machine; protected Dictionary<EState, StateType> _statesCached = new Dictionary<EState, StateType>(); public StateFactory(StateMachine<EState, StateType> machine, bool cacheStates = true) { _machine = machine; InstantiateStates(); } protected abstract void InstantiateStates(); //无关代码 }
核心问题
编写继承自BaseState的层级状态类HBaseState构造器时,C#无法将StateMachine<EState, HBaseState<EState>>转换为StateMachine<EState, BaseState<EState>>,导致无法将参数传递给基类BaseState的构造器,强制类型转换也无效。
请问我的泛型实现是否正确?该如何重构代码以解决此问题?
解决方案
问题根源
你的泛型设计存在不变性约束问题:StateMachine<EState, StateType>是泛型类,C#中泛型类默认是不变的——即使HBaseState<EState>继承自BaseState<EState>,StateMachine<EState, HBaseState<EState>>也不能被视为StateMachine<EState, BaseState<EState>>的子类,两者属于完全不同的类型,因此无法直接转换。
重构方案:让BaseState支持泛型状态类型
修改BaseState的定义,引入第二个泛型参数StateType,让基类能够适配不同的状态子类,解决类型不兼容问题。
1. 修改BaseState类
public abstract class BaseState<EState, StateType> where EState : Enum where StateType : BaseState<EState, StateType> { protected StateFactory<EState, StateType> _factory; protected StateMachine<EState, StateType> _machine; protected EState _stateKey; public BaseState(EState stateKey, StateMachine<EState, StateType> machine, StateFactory<EState, StateType> factory) { _stateKey = stateKey; _machine = machine; _factory = factory; } //无关逻辑 }
2. 修改HBaseState类
让HBaseState继承自新的BaseState,并指定自身为StateType参数:
public abstract class HBaseState<EState> : BaseState<EState, HBaseState<EState>> where EState : Enum { protected bool _isRootState = false; protected HBaseState<EState> _parentState; protected HBaseState<EState> _childState; public HBaseState(EState stateKey, StateMachine<EState, HBaseState<EState>> machine, StateFactory<EState, HBaseState<EState>> factory, bool isRootState = false) : base(stateKey, machine, factory) { _isRootState = isRootState; // 无需重复赋值_stateKey,基类构造器已处理 } //无关逻辑 }
3. 调整StateMachine的约束
确保StateMachine的StateType约束匹配新的BaseState定义:
public abstract class StateMachine<EState, StateType> : MonoBehaviour where EState : Enum where StateType : BaseState<EState, StateType> { protected StateFactory<EState, StateType> _factory; public StateType _currentState; //无关逻辑 }
4. 调整StateFactory的约束
同样更新StateFactory的泛型约束:
public abstract class StateFactory<EState, StateType> : MonoBehaviour where EState : Enum where StateType : BaseState<EState, StateType> { protected StateMachine<EState, StateType> _machine; protected Dictionary<EState, StateType> _statesCached = new Dictionary<EState, StateType>(); public StateFactory(StateMachine<EState, StateType> machine, bool cacheStates = true) { _machine = machine; InstantiateStates(); } protected abstract void InstantiateStates(); //无关代码 }
额外优化建议
- 去掉
HBaseState构造器中重复的_stateKey赋值,基类构造器已完成该操作,避免冗余。 - 如果需要支持普通非层级状态,可以新增
SimpleBaseState<EState>类,继承自BaseState<EState, SimpleBaseState<EState>>,保持状态机的扩展性。
内容的提问来源于stack exchange,提问作者Vinh Nguyễn
相关产品推荐
相关产品推荐

