在此之前,一直对有限状态机有一个比较抽象的理解,看过好几个教程,似懂非懂的感觉,直接上手代码个人觉得是比较吃抽象的理解起来有限状态机
其实通过一个比喻就可以很好的理解有限状态机了,就是Unity中的Animator
通过这样的比喻理解 就很形象了
首相先创建一个BaseState,包含三个抽象函数,因为每个状态都要有 进入 处于 退出 三个行为,将这个BaseState写成接口或抽象类都可,如果为了后续有非抽象成员需要添加在状态中,建议改为抽象类,在这里使用抽象类
//单个状态的基类 每个单独的基本状态都要继承这个类
//每个状态都有进入 保持 退出 三个状态
public abstract class BaseState
{
public abstract void Enter();
public abstract void Update();
public abstract void Exit();
}
所有的单个状态都必须继承这个抽象类,这里BaseState规范了每个状态的行为
创建FSM_Contronller脚本管理和控制状态的切换
public enum StateType
{
Idle,
Move,
Dead
}
//可以将FSM_Contronller喻为Unity中的Animator
public class FSM_Controller
{
//当前状态
private BaseState currentState;
//状态的类型
public StateType stateType;
//存储所有状态的容器
private Dictionary<StateType, BaseState> allSaveState;
public FSM_Controller()
{
//初始化容器
allSaveState = new Dictionary<StateType, BaseState>();
}
//保持当前状态
public void OnUpdate()
{
currentState?.Update();
}
public void AddState(StateType stateType, BaseState state)
{
//先判断状态容器中是否包含此态,重复状态不添加
if (allSaveState.ContainsKey(stateType))
return;
allSaveState.Add(stateType, state);
}
//状态切换
public void SetState(StateType stateType)
{
//如果当前状态和要跳转的状态相同 则不切换
if (currentState == allSaveState[stateType])
{
return;
}
//如果当前状态不为空 则退出当前状态
currentState?.Exit();
//将当前状态改为要跳转的状态
currentState = allSaveState[stateType];
//第一次进入状态 需要执行一次Enter
currentState.Enter();
}
}
代码解释:
首先需要三个必要的变量 当前状态 状态类型 存储状态的容器
用字典存储所有的状态,一对一进行存储,字典中的键就为枚举的状态类型,值就为继承了BaseState的所有状态类,字典中的值用BaseState直接替代,符合面向对象(里氏转换原则)
需要有个构造函数 初始化状态容器
OnUpdate函数 保持处于某个状态
AddSatate函数 添加状态到容器中去 添加的时候要先进行判断
SetState函数 切换状态
以Idle State为例:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class IdleState : BaseState
{
private Animator animator;
private FSM_Controller fsm;
private float stateCoolDown = 3f;
public IdleState(Animator animator, FSM_Controller fsm)
{
//如果有其他组件 如Animator 就在此一起初始化了
this.animator = animator;
this.fsm = fsm;
}
public override void Enter()
{
Debug.Log("进入Idle状态");
}
public override void Update()
{
Debug.Log("处于Idle状态");
stateCoolDown -= Time.deltaTime;
//过5秒切换状态
if (stateCoolDown <= 0)
{
fsm.SetState(StateType.Move);
}
}
public override void Exit()
{
Debug.Log("退出Idle状态");
}
}
继承BaseState 都必须实现三个行为 进入状态 处于 退出 在这个状态分别要做什么
扫描二维码关注公众号,回复:
16106195 查看本文章
![](/qrcode.jpg)
同时得包含FSM_Contronller对象的引用 以及初始化 便于在状态内切换到另一个状态
在Update中 三秒后切换状态到另一个状态Move