简单的状态机
提示:本篇写的是基于对有限状态机的理解自己写的一个简单的状态机,简单清晰明了
FSMSystem脚本 状态
using System.Collections.Generic;
using UnityEngine;
public class FSMSystem
{
private Dictionary<StateID, FSMState> states = new Dictionary<StateID, FSMState>();
private StateID CurrentID;
private FSMState CurrentState;
public void Update(GameObject npc)
{
CurrentState.Act(npc);
CurrentState.Reason(npc);
}
//添加状态
public void AddState(FSMState state)
{
if (state == null)
{
Debug.LogError("当前状态为空");
return;
}
if (CurrentState == null)
{
CurrentState = state;
CurrentID = state.ID;
}
if (states.ContainsKey(state.ID))
{
Debug.LogError("不能重复添加状态" + state);
return;
}
states.Add(state.ID,state);
Debug.Log(state.ID);
}
//删除状态
public void DeleteState(StateID id)
{
if (id == StateID.NullStateID)
{
Debug.LogError("ID为空");
return;
}
if (!states.ContainsKey(id))
{
Debug.LogError("id不存在");
return;
}
states.Remove(id);
}
//通过条件,跳转状态
public void PerformTransition(Transition trans)
{
if(trans==Transition.NullTransition)
{
Debug.LogError("条件为空");
return;
}
StateID id = CurrentState.GetOutputState(trans);
if (id == StateID.NullStateID)
{
Debug.LogWarning("ID为空,无法转换");
return;
}
if (!states.ContainsKey(id))
{
Debug.LogError("状态机不包含当前状态");
return;
}
FSMState state = states[id];
Debug.Log("state" + states[id]);
CurrentState.DoAfterLeaving();
CurrentState = state;
CurrentID = id;
CurrentState.DoBeforeEntering();
}
}
FSMState 状态机脚本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum Transition//状态条件
{
NullTransition=0,
Work,//工作条件
Free,//空闲条件
}
public enum StateID//状态ID
{
NullStateID = 0,
Free,//空闲
Working,//工作状态
}
public abstract class FSMState
{
protected StateID stateID;
public StateID ID
{
get { return stateID; }
}
protected FSMSystem fsm;
public FSMState( FSMSystem fsm)
{
this.fsm = fsm;
}
存放当前转换条件 与ID
protected static Dictionary<Transition, StateID> map = new Dictionary<Transition, StateID>();
//添加状态字典内容
public void AddTransition(Transition trans,StateID id)
{
if (trans == Transition.NullTransition)
{
Debug.LogError("不允许添加NullTransition");
return;
}
if (id == StateID.NullStateID)
{
Debug.LogError("不允许添加NullStateID");
return;
}
if (map.ContainsKey(trans))
{
Debug.LogError("添加的条件已经存在");
return;
}
map.Add(trans, id);
foreach (Transition t in map.Keys)
{
Debug.Log("map" + t);
}
}
//删除状态字典内容
public void DeleteTransition(Transition trans)
{
if (trans == Transition.NullTransition)
{
Debug.LogError("不能删除状态NullTransition");
return;
}
if (!map.ContainsKey(trans))
{
Debug.LogError("删除状态不存在");
return;
}
map.Remove(trans);
}
//根据输入条件返回要跳转的状态
public StateID GetOutputState(Transition trans)
{
if (map.ContainsKey(trans))
{
return map[trans];
}
return StateID.NullStateID;
}
//进入当前状态前执行函数
public virtual void DoBeforeEntering()
{
}
//离开当前状态前执行函数
public virtual void DoAfterLeaving()
{
}
//在这个状态的时候要做什么事情 一直执行
public abstract void Act(GameObject npc);
//达到某种条件 判断当前状态的离开条件 一直执行
public abstract void Reason(GameObject npc);
}
每一种状态都需要继承FSMState类,并在调用脚本添加更新自己的update,添加自己的生命周期
初始化自己的所有状态,并添加到自己存储状态的字典之中