1.枚举的切换条件
//有哪些状态切换条件
public enum ETransition
{
NullTransition =0,
SawPlayer,//看见主角
LosePlay//丢失主角
}
2.枚举的所有状态(唯一状态)
//状态id,表示有哪些状态,每一个状态的唯一标志,
public enum EStateID
{
NullStateID = 0,
Patrol,//巡逻状态
Chase//追逐状态
}
3.抽象的状态类State
public abstract class FSMState{
//状态对应的ID,我们为了方便的获取FSMState
protected EStateID m_stateID;
//指定某个状态是由哪个状态机控制的,哪怕是同一类的两个敌人,也有两个状态机
public FSMSystem m_system;
public EStateID m_StateID { get{return m_stateID; }}
protected Dictionary
protected FSMState()
{
m_tranDic = new Dictionary
}
//1.添加一个在该状态可以通过某个条件切换到某个状态
public void _AddTransition(ETransition tran,EStateID id)
{
if (tran == ETransition.NullTransition || id == EStateID.NullStateID)
{
Debug.LogError("you add a null ERtansition or a null EStateID");
return;
}
if (m_tranDic.ContainsKey(tran))
{
Debug.LogError("m_tranDic is alreadey contains the key");
return;
}
m_tranDic.Add(tran, id);
}
//2.删除一个在该状态的切换条件
public void _DeleteTransition(ETransition tran)
{
if (m_tranDic.ContainsKey(tran) == false)
{
Debug.LogWarning("you want to delete a not exist key" + tran);
return;
}
m_tranDic.Remove(tran);
}
//3.通过某个切换条件得到这个条件要切换的状态
public EStateID _GetStateID(ETransition tran)
{
if (m_tranDic.ContainsKey(tran))
{
return m_tranDic[tran];
}
return EStateID.NullStateID;
}
//在某个状态进入之前要做的动作
public virtual void _OnEnterBefore() { }
//在某个状态持续中要做的动作
public abstract void _OnStayUpdate();
//在某个状态即将推出的时候要做的动作
public virtual void _OnQuitBefore() { }
}
4.所有的状态管理类:状态机System
public class FSMSystem
{
//当前状态机有哪些状态
private Dictionary
//状态机处于什么状态
private FSMState m_currentState;
public FSMState m_CurrentState {get{ return m_currentState;} }
public FSMSystem()
{
m_statesDic = new Dictionary
}
//1.在一个特定的某个角色的状态机上,标志哪个状态是开始状态
public void _StartFSM(EStateID startStateID)//即为图中的Register方法,注意的是:只指定开始状态是谁,而不是指定状态机是谁
{
FSMState state;
bool isGet = m_statesDic.TryGetValue(startStateID,out state);
if (state == null)
{
Debug.Log(startStateID + " not exist fsmState");
}
else
{
m_currentState = state;
m_currentState._OnEnterBefore();
}
}
//2.给某个角色状态机添加一个状态(该状态的枚举和该状态)
public void _AddStateID(FSMState state)
{
if (state == null)
{
Debug.LogError("id is null of nullStateID");
return;
}
if (m_statesDic.ContainsKey(state.m_StateID))
{
Debug.Log(state + "the staete is already exist");
}
m_statesDic.Add(state.m_StateID, state);
//设置这个状态的状态机是谁,每个敌人的状态机都是不相同的,这就是初始化的过程
state.m_system = this;
}
public void _DeleteState(FSMState state)
{
if (m_statesDic.ContainsKey(state.m_StateID) == false)
{
Debug.Log(state + " is not exist");
}
else
m_statesDic.Remove(state.m_StateID);
}
//3.在当前状态下给予一个切换条件,如果成立,则切换到另外状态
public void _PerformTransition(ETransition tran)
{
if (tran == ETransition.NullTransition)
{
Debug.Log("tran is nullTransiion"); return;
}
EStateID id = m_currentState._GetStateID(tran);
if (id == EStateID.NullStateID)
{
Debug.Log("transition is not be happend"); return;
}
FSMState state;
m_statesDic.TryGetValue(id, out state);
//当前状态退出
m_CurrentState._OnQuitBefore();
//切换到一个新状态
m_currentState = state;
m_currentState._OnEnterBefore();
}
}
5.继承了状态类的某个NPC
public class NPCControl : MonoBehaviour {
private FSMSystem m_fsm;
public GameObject m_npc;
public Transform[] m_pathPointTras;
public Transform m_target;
void Start()
{
_InitFSM();
}
void Update()
{
//调用当前状态的持续方法
m_fsm.m_CurrentState._OnStayUpdate();
}
void _InitFSM()
{
m_fsm = new FSMSystem();
PatrolState patrolState = new PatrolState(m_pathPointTras,m_npc,m_target);
patrolState._AddTransition(ETransition.SawPlayer, EStateID.Chase);
ChaseState chaseState = new ChaseState(m_npc,m_target);
chaseState._AddTransition(ETransition.LosePlay, EStateID.Patrol);
m_fsm._AddStateID(patrolState);
m_fsm._AddStateID(chaseState);
m_fsm._StartFSM(EStateID.Patrol);
}
}
6.该NPC的行为之一:巡逻
需要在里面设置他所属的的State
做具体的事情以及切换到其他状态
7.该NPC的行为之二:追逐
做具体的事情以及切换到其他状态
附带普通的状态模式
//一个引用状态的类
class Context
{
IState state;
//指定初始化的状态
public void _SetState(IState state)
{
this.state = state;
}
public void _Show(int arg)
{
state._Show(arg);
}
}
//状态类接口
interface IState
{
void _Show(int arg);
}
class StateA:IState
{
Context c;
//指定他所属于哪个调用他的类
public StateA(Context c)
{
this.c = c;
}
public void _Show(int arg)
{
if (arg > 10)
{
Debug.Log("开始处理");
}
else
{
Debug.Log("处理不了,开始转换");
//否则的话切换状态
c._SetState(new StateB(c));
}
}
}
class StateB : IState
{
Context c;
public StateB(Context c)
{
this.c = c;
}
public void _Show(int arg)
{
if (arg < 10)
{
Debug.Log("开始处理");
}
else
{
Debug.Log("处理不了,开始转换");
c._SetState(new StateA(c));
}
}
}
//调用在unity里调用
public class StatePattern : MonoBehaviour {
void Start()
{
Context c = new Context();
c._SetState(new StateA(c));
c._Show(15);
c._Show(5);
c._Show(5);
c._Show(35);
c._Show(25);
}
}