Unity —有限状态机FSM系统(一)
什么是FSM状态机
总的来说,有限状态机系统,是指不同的阶段呈现出不同的运行状态系统,这些状态是有限的,不重叠,这样的系统在某一时刻一定会处于其所有状态中的一个状态,此时他接受一部分允许的输入,产生一部分可能的响应,并且迁移到一部分可能的状态。
五大要素
- 状态
- 事件
- 条件
- 动作
- 迁移
游戏运用
案例演示
说明:Enemy 是游戏中的一个敌人脚本类,持有FSMSystem(状态管理类),通过改变敌人的状态(FSMState)来实现敌人在不同状态市因执行什么样的操作。 StateID (状态ID),Transiton (状态类型)。
功能
敌人在三个点之间巡逻(巡逻状态),当主角靠近时,敌人切换到跟随状态,(跟随状态),当主角离远时,敌人切换到巡逻状态。
FSMState 状态父级类
定义状态父级类,之后的每个状态子类都继承于FSMState类。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum Transiton
{
NullTransiton = 0,
SeePlayer = 1,
LostPlayer = 2,
}
public enum StateID //状态id
{
NullStateID = 0,
patrol = 1,
Chase = 2,
}
/// <summary>
/// 状态机框架
/// </summary>
public abstract class FSMState
{
protected StateID stateID;
public StateID ID { get { return stateID; } }
protected Dictionary<Transiton, StateID> map = new Dictionary<Transiton, StateID>();
protected FSMSystem fsm;
public FSMState(FSMSystem _fsm)
{
fsm = _fsm;
}
//添加转换条件
public void AddTransition(Transiton trans, StateID id)
{
if (trans == Transiton.NullTransiton)
{
Debug.LogError("..................");
return;
}
if (id == StateID.NullStateID)
{
Debug.LogError("=================");
return;
}
map[trans] = id;
}
public void DeleteTransition(Transiton trans)
{
if (trans == Transiton.NullTransiton)
{
return;
}
if (map.ContainsKey(trans) == false)
{
return;
}
map.Remove(trans);
}
/// <summary>
/// 获取状态
/// </summary>
/// <param name="trans"></param>
/// <returns></returns>
public StateID GetQutputState(Transiton trans)
{
if (map.ContainsKey(trans))
{
return map[trans];
}
return StateID.NullStateID;
}
//状态的生命周期
public virtual void DobeforEntering() { } //进入状态
public virtual void DoAfterLeaving() { } //俩开状态
public abstract void Act(GameObject npc); //当前状态要做的事情
public abstract void Reason(GameObject npc); //判断转换条件
}
FSMSystem 状态管理类
FSMSystem持有FSMState对象,通过管理FSMState对象进行状态的切换,达到控制敌人在什么情况执行什么样的状态。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 状态机框架 管理类
/// </summary>
public class FSMSystem
{
private Dictionary<StateID, FSMState> states = new Dictionary<StateID, FSMState>();
//当前状态
private StateID currentStateID;
private FSMState currentState; //状态对象
public void Update(GameObject go)
{
currentState.Act(go);
currentState.Reason(go);
}
//状态添加
public void AddSatte(FSMState state)
{
if (state == null)
{
return;
}
if (currentState == null)
{
currentState = state;
currentStateID = state.ID;
}
if (states.ContainsKey(state.ID))
{
return;
}
states.Add(state.ID, state);
}
public void DeleteSatte(StateID id)
{
if (id == StateID.NullStateID)
{
return;
}
if (states.ContainsKey(id))
{
return;
}
states.Remove(id);
}
//状态切换
public void PerformTransition(Transiton trans)
{
if (trans == Transiton.NullTransiton)
{
return;
}
StateID id = currentState.GetQutputState(trans); //判断是否需要转换
if (id == StateID.NullStateID)
{
return;
}
//可以转换
if (states.ContainsKey(id) == false)
{
//不存在
return;
}
FSMState state = states[id];
currentState.DoAfterLeaving();
currentState = state;
currentStateID = id;
currentState.DobeforEntering();
}
}