Unity-FSM

前言

FSM

设想这么一个状态机,默认IDLE状态,一个巡逻PATROL,一个CHASE追逐状态。

默认进入IDLE,IDLE-A 进入PATROL,PATROL-B进入CHASE,CHASE-C进入PATROL,PATROL-D进入IDLE,任何条件,按O进入IDLE

枚举设计:
​ 状态枚举StateID,所有状态
​ 跳转枚举,所有跳转

类的设计:
-核心类是每个状态 FSMState基类,每个状态负责 :
1 维护该状态state以及StateID
2 维护FSMSystem实体,只有一个
3 维护<跳出条件trans,目标状态targetState>字典(可以通过条件A跳到状态2)
4 状态执行Act、跳出动作Leave(执行FSMSystem的doTrans)+准备事宜
子类负责具体实现状态

​ -状态机管理类 FSMSystem,它负责 :
​ 1 维护状态字典<stateID,FSMState>stateDict、当前状态currentState
​ 2 执行状态转换doTrans,根据transition得到目标状态targetState
​ 3 更新update,执行当前状态的Act+Leave

Usage
​ 1 实例化FSMSystem
​ 2 创建和添加状态
​ 3 添加Transition,注意进行FSM状态机的初始化
​ 4 更新FSMSystem的update

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
public enum StateID
{
IdleState,
PatrolState,
ChaseState
}

public enum Transition
{
BackToIdle,//
Idle2Patrol,//
Patrol2Chase,//FindPlayer
Chase2Patrol//LosePlayer
}

public abstract class FSMState
{
public StateID ID { get { return this.stateID; } }
protected StateID stateID;
//转换条件trans-将要变成的状态targetStateID
protected Dictionary<Transition,StateID> map = new Dictionary<Transition, StateID>();
protected FSMSystem fsmanager;

public FSMState(FSMSystem fsm)
{
this.fsmanager = fsm;
}

public void AddTrans(Transition trans,StateID stateID)
{
map.Add (trans,stateID);
}

public void deleteTrans(Transition trans)
{
map.Remove (trans);
}

public StateID getTargetStateID(Transition trans)
{
return map [trans];
}

public virtual void Before(){}
public virtual void After(){}
public abstract void Act ();
public abstract void Leave ();
}

public class FSMSystem
{
private Dictionary<StateID,FSMState> stateDict = new Dictionary<StateID, FSMState>();
public FSMState currentState;

public void updateFSM()
{
currentState.Act ();
currentState.Leave ();
}

public void AddState(FSMState state)
{
stateDict.Add (state.ID,state);
}
public void deleteState(FSMState state)
{
stateDict.Remove (state.ID);
}
public void doTrans(Transition trans)
{
FSMState targetState = stateDict[currentState.getTargetStateID(trans)];
currentState.Before ();
targetState.After ();
currentState = targetState;
}
}

///具体的state子类
public class IdleState:FSMState
{
public IdleState(FSMSystem fsm):base(fsm)
{
stateID = StateID.IdleState;
}

public override void Before()
{
Debug.Log ("idle before.....");
}
public override void After()
{
Debug.Log ("idle after....");
}
public override void Act ()
{
Debug.Log ("idle Entering--------");
}
public override void Leave ()
{
if(Input.GetKeyDown(KeyCode.A))
{
fsmanager.doTrans (Transition.Idle2Patrol);
Debug.Log ("idle - patrol.....");
}
}
}

//Usage
public class testFSM : MonoBehaviour {
private FSMSystem myfsm;

// Use this for initialization
void Start () {
myfsm = new FSMSystem ();
FSMState ilde = new IdleState (myfsm);
FSMState patrol = new PatrolState (myfsm);
FSMState chase = new ChaseState (myfsm);

myfsm.AddState (ilde);
myfsm.AddState (patrol);
myfsm.AddState (chase);

myfsm.currentState = ilde;

ilde.AddTrans (Transition.Idle2Patrol,StateID.PatrolState);
patrol.AddTrans (Transition.Patrol2Chase,StateID.ChaseState);
patrol.AddTrans (Transition.BackToIdle,StateID.IdleState);
chase.AddTrans (Transition.Chase2Patrol,StateID.PatrolState);
chase.AddTrans (Transition.BackToIdle,StateID.IdleState);

}

// Update is called once per frame
void Update () {
myfsm.updateFSM ();
}
}

FSM参考:
https://blog.csdn.net/qq_35361471/article/details/79847734
https://www.cnblogs.com/linkshow/p/9781255.html
https://blog.csdn.net/silangquan/article/details/51155805