1.这是State的实现:
public
class
State
{
private
readonly
List<StateTransition> transitions =
new
List<StateTransition>();
protected
Action StartAction {
get
;
set
; }
protected
Action StopAction {
get
;
set
; }
protected
Action UpdateAction {
get
;
set
; }
protected
internal
bool
IsStarted {
get
;
set
; }
protected
internal
void
Start()
{
if
(!IsStarted && StartAction !=
null
)
{
StartAction();
IsStarted =
true
;
}
}
protected
internal
void
Update()
{
if
(IsStarted && UpdateAction !=
null
)
{
UpdateAction();
}
}
protected
internal
void
Stop()
{
if
(IsStarted && StopAction !=
null
)
{
StopAction();
IsStarted =
false
;
}
}
public
State AddStartAction(Action startAction)
{
StartAction += startAction;
return
this
;
}
public
State AddUpdateAction(Action updateAction)
{
UpdateAction += updateAction;
return
this
;
}
public
State AddStopAction(Action stopAction)
{
StopAction += stopAction;
return
this
;
}
public
State AddTransition(Predicate<State> condition, State nextState)
{
transitions.Add(
new
StateTransition(condition, nextState));
return
this
;
}
public
bool
CanGoToNextState(
out
State nextState)
{
for
(
int
i = 0; i < transitions.Count; i++)
{
if
(transitions[i].Condition(
this
))
{
nextState = transitions[i].NextState;
return
true
;
}
}
nextState =
null
;
return
false
;
}
public
bool
HasNextState()
{
return
transitions.Count != 0;
}
}
public
class
StateTransition{
public Predicate<State> Condition;
public State NextState;
public
StateTransition(Predicate<State> condition,State nextState){
Condition=condition;
NextState=nextState;
}
}
2.这是StateMachine的实现:
public
class
StateMachine : State
{
private
readonly
State initialState;
public
State CurrenState {
get
;
private
set
; }
public
StateMachine(State initialState)
{
this
.initialState = initialState;
StartAction = Start;
UpdateAction = Update;
StopAction = Stop;
}
public
new
void
Start()
{
if
(IsStarted)
{
return
;
}
CurrenState = initialState;
CurrenState.Start();
IsStarted =
true
;
}
public
new
void
Update()
{
if
(CurrenState ==
null
)
{
return
;
}
if
(!CurrenState.IsStarted)
{
CurrenState.Start();
}
CurrenState.Update();
State nextState;
while
(CurrenState.CanGoToNextState(
out
nextState))
{
if
(CurrenState.IsStarted)
{
CurrenState.Stop();
}
CurrenState = nextState;
if
(!CurrenState.IsStarted)
{
CurrenState.Start();
}
CurrenState.Update();
}
if
(!CurrenState.HasNextState())
{
Stop();
}
}
public
new
void
Stop()
{
if
(CurrenState ==
null
)
{
return
;
}
if
(CurrenState.IsStarted)
{
CurrenState.Stop();
}
CurrenState =
null
;
}
}
Test:
public
class
Test : MonoBehaviour
{
private
StateMachine stateMachine;
private
State firstState =
new
State();
private
State secondState =
new
CustomState();
private
State finishState =
new
State();
// Use this for initialization
void
Start ()
{
var initChild =
new
State()
.AddStartAction(() => Debug.Log(Time.frameCount +
" childInit Start"
))
.AddUpdateAction(() => Debug.Log(Time.frameCount +
" childInit Update"
))
.AddStopAction(() => Debug.Log(Time.frameCount +
" childInit Stop"
));
var childStateMachine =
new
StateMachine(initChild);
stateMachine =
new
StateMachine(firstState);
firstState
.AddStartAction(() => Debug.Log(Time.frameCount +
" 1 Start"
))
.AddUpdateAction(() => Debug.Log(Time.frameCount +
" 1 Update"
))
.AddStopAction(() => Debug.Log(Time.frameCount +
" 1 Stop"
))
.AddTransition(
state => Time.frameCount == 5,
secondState)
.AddTransition(
state => Time.frameCount == 15,
secondState);
secondState
.AddTransition(
state => Time.frameCount == 10,
firstState)
.AddTransition(
state => Input.GetKey(KeyCode.Q),
childStateMachine);
childStateMachine
.AddTransition(s => Input.GetKey(KeyCode.Y), finishState);
finishState
.AddStartAction(() => Debug.Log(Time.frameCount +
" finish Start"
));
stateMachine.Start();
}
void
Update()
{
stateMachine.Update();
}
}
public
class
CustomState : State
{
public
CustomState()
{
StartAction = CustomStart;
UpdateAction = CustomUpdate;
StopAction = CustomStop;
}
public
void
CustomStart()
{
Debug.Log(Time.frameCount +
" custom start"
);
}
public
void
CustomUpdate()
{
Debug.Log(Time.frameCount +
" custom update"
);
}
public
void
CustomStop()
{
Debug.Log(Time.frameCount +
" custom stop"
);
}
}