FSM状态机的介绍百度必应一大堆,这里就不多讲了,主要讲讲如何实现吧。状态机主要一大优点就是可以处理复杂的状态,例如格斗游戏里拳、腿、跳、搓招等关系,如果只写成switch的话会加大维护难度,case太多代码的可读性大大降低,所以就需要状态机来维护。可以应用在Animator
、AI巡逻、技能衔接等方面,接下来就讲如何实现一个简单的状态机吧。
首先清楚,虽然状态机基类和管理者不继承自MonoBehavior
,但仍需通过继承自MonoBehavior
的类来控制(不然就没法实现了),所以理所当然的需要Update、FixedUpdate等函数。为了通用所以采用泛型来实现,使用struct,Enum约束T只能为枚举类型。(为什么要用枚举呢,因为用sbyte代码可读性太差了,没有人可以知道01代表什么状态)因为是基类所以用abstract修饰。
public abstract class FSMManagerBase<T> where T:struct,Enum
{
protected FSMManagerBase()
{
}
public void Update()
{
}
public void FixedUpdate()
{
}
}
public abstract class FSMBase<T> where T:struct,Enum
{
protected FSMBase()
{
}
public abstract void OnEnter();
public abstract void OnUpdate();
public abstract void OnFixedUpdate();
public abstract void OnExit();
}
接下来向类中添加字段和属性,每个状态类必然会有一个状态,而这个状态是T类型的,也就是枚举类型,所以要向FSMBase
添加ClassState
属性:public abstract T ClassState { get; protected set; }
而管理者类也需要知道当前调用状态的属性,所以添加:public FSMBase<T> CurrentState { get; protected set; }
既然已经得知当前状态,那也应该得知管理者管理的到底是哪些状态,便于读取操作这里用字典实现:public Dictionary<T, FSMBase<T>> fsmDictionary;
而这个字典可以从外界传入,也可以类内生成后提供方法添加,所以在构造函数做些改动即可实现,所以现在类就变成了这样。
public abstract class FSMManagerBase<T> where T:struct,Enum
{
public Dictionary<T, FSMBase<T>> fsmDictionary;
public FSMBase<T> CurrentState {
get; protected set; }
protected FSMManagerBase(Dictionary<T, FSMBase<T>> dictionary)
{
fsmDictionary = dictionary;
}
protected FSMManagerBase()
{
fsmDictionary = new Dictionary