Unity FSM的原理及实现
按照规矩上代码前先来一键三连,搞错了重来,先来一键三问。1.什么是FSM?
2.FSM能干什么?
3.为什么要用FSM?
对于上面三个问题,我们一一解答
1.FSM全称是Finite State Machine,中文名是有限状态机,为什么叫有限状态机?有限指的是状态的个数是有限的。
2.FSM是管理一组能相互切换状态的机器。
3.举个例子:我们有如下状态和条件
1.1
我们发现当前处于某个状态下的条件一旦满足,就会切换到另一个状态,也就是条件驱动状态的切换。当状态和条件复杂的时候就需要FSM对这些东西进行管理。
解决了一键三问,我们来看看FSM到底要怎么实现。
还是使用图1.1的例子我们先分析一下,状态对应不同的判断条件,而且以后肯定会增加新条件或者改变条件,如果条件写在对应状态里面,那条件发生改变的时候状态类也要去改动,根据面向对象的模式这违反了开闭原则,我们需要把条件写成类,这样增加条件或者修改条件我们只需要对条件类进行处理。
我们现在知道条件应该做成一个类,那么条件类具体应该干什么呢?
图1.1条件类就是处理条件判断的逻辑,查看自己是否满足了,满足就要切换到下一个状态。
拿检测到移动输入/跳跃输入举例我们来写一些伪代码
class InputMovingCondition{class InputJumpingCondition{
public bool IsInputMoving() {public bool IsInputJumping() {
if(正在移动输入) if(正在跳跃输入){
return true return true
else else
return false return false
} }
} }
说完条件类,我们来看下状态类,状态类到底应该干什么呢?
图1.1,我们发现状态类里面要应该要存放多个条件满足->切换状态的对应关系,然后需要遍历所有条件,看一下哪个条件满足了,满足之后就要去通知状态机切换到对应的状态。而且每个状态要执行的逻辑也各不相同,移动跳跃或是攻击等等。
最后状态机到底干什么呢?
图1.1并没有标出状态机,状态机在后台把控全局类似军师的角色,当前是什么状态,状态怎么切换这些都是状态机去负责的。
根据上面的分析,我们先写以下的代码
条件基类:
条件基类
状态基类:
状态基类
状态机基类:
状态机基类
基本的框架已经搭好了,里面还有些地方我们需要改动,我们接往下走
先看状态基类,mapping这个参数还没有设置,对应关系应该是状态机为状态设置的,状态基类中处理状态的地方不够详细,我们可能需要状态进入和状态退出的事件,这也需要状态机去提供,分析了这些之后再去进行修改
条件基类:
public abstract class FSMCondition
{
//我只知道我要条件判断,具体判断什么要让子类重写
public abstract bool HandleCondition(FSMBase fsmBase);
}
状态基类:
public abstract class FSMState
{
//条件->状态的对应关系
private Dictionary<FSMCondition,FSMState> mapping;
//由状态机为我们配置映射关系
public void ConfigMapping(FSMCondition condition, FSMState state)
{
mapping.Add(condition,state);
}
//这方法让状态机每帧去调用判断
public void CheckCondition(FSMBase fsmBase)
{
//便利自身所有的条件
foreach(FSMCondition condition in mapping.Keys)
{
if(condition.HandleCondition(fsmBase))
{
//告诉状态机切换到对应状态,那参数需要FSMBase
fsmBase.SwitchState(mapping);
return;
}
}
}
//状态中自己要干的事,具体做什么还是要子类去重写
public abstract void OnStateEnter(FSMBase fsmBase);
public abstract void OnStateStay(FSMBase fsmBase);
public abstract void OnStateExit(FSMBase fsmBase);
}
状态机基类:
public abstract class FSMBase : MonoBehaviour
{
//当前在哪个状态
protected FSMState currentState;
//添加状态,并为每个状态去设置应对关系
protected abstract void AddStateAndConfigMapping();
//切换状态,切到哪个状态?由状态类调用
public void SwitchState(FSMState fsmState)
{
currentState.OnStateExit(this);//退出旧状态
currentState = fsmState;
currentState.OnStateEnter(this);//进入新状态
}
protected void Start()
{
AddStateAndConfigMapping();
}
protected void Update()
{
//调用状态类里面的条件判断
currentState.CheckCondition(this);
currentState.OnStateStay(this);//正在状态中
}
}
FSM写完后,我们用图1.1案列去使用一下
状态机类:
用户控制的状态机
状态类:
闲置状态类
移动状态类
跳跃状态类
条件类:
检测跳跃输入
检测跳跃结束
检测移动输入
检测停止移动输入
FSM的简单实现就完成了
页:
[1]