1.作用
?待定
2.所需脚本
fsm在有限的状态下进行状态的切换,所以在代码层面,我们需要一个总览的fsm脚本,记作FSM
对于不同的状态,为了使fsm更好的切换,且减少代码量,所以需要通过基类来调用,记作BaseState
并且为了更好区分每个状态,通过枚举为其命名,记为StateEnum
故在编辑器层面,我们需要创造以下脚本,FSM,BaseState,StateEnum,以及以BaseState为基类的各类状态
3.实现顺序
在有限状态机中很明显,各式状态是基石,我们需要先确定好状态的枚举,然后实现状态的基类,所以我们的编写过程将从StateEnum->BaseState->各式状态->fsm
4.在人物控制中的具体实现
首先是StateEnum,随项目而定
public enum CharacterStateEnum
{
IDLE,
JUMP,
MOVE,
}
其次是BaseState,首先我们需要在构造函数中知悉其运行该状态的fsm,改状态实现的内容,然后是状态的初始化,状态转换过程中需要实现的代码,以及在此状态下的活动
public abstract class BaseState
{
protected CharacterFSM cfsm;
protected Animation animator;
protected CharacterStateEnum currentState;
public BaseState(CharacterFSM cfsm, Animation animation,CharacterStateEnum cs)
{
this.cfsm = cfsm;
this.animation = animation;
this.currentState = cs;
}
public abstract void InitState();
public abstract void StateUpdate();
public abstract void EnterState();
public abstract void ExitState();
}
然后是各类状态的编写。
最后便是FSM的编写,首先可以通过字典对所有状态进行存储,记录一下前置状态以及当前状态,以便后续状态的更新。函数方面需要一个调用所有状态初始化的方法,状态转换的方法,以及当前状态运行的方法
public class CharacterFSM : MonoBehaviour
{
private Dictionary<CharacterStateEnum, BaseState> stateDict;
public BaseState currentState;
public BaseState LastState;
public void InitCharacterFSM(Animator animator)
{
stateDict = new Dictionary<CharacterStateEnum, BaseState>()
{
{CharacterStateEnum.IDLE,new IdleState(this,animator,CharacterStateEnum.IDLE) },
{CharacterStateEnum.MOVE,new MoveState(this,animator,CharacterStateEnum.MOVE) },
{CharacterStateEnum.JUMP,new JumpState(this,animator,CharacterStateEnum.JUMP) }
};
SetDefaultState();
}
public void SetDefaultState()
{
foreach (var item in stateDict)
{
item.Value.InitState();
}
currentState = stateDict[CharacterStateEnum.IDLE];
currentState.EnterState();
}
public void ChangeState(CharacterStateEnum stateEnum)
{
if(stateDict.ContainsKey(stateEnum))
{
BaseState temp= stateDict[stateEnum];
if (temp != currentState)
{
currentState.ExitState();
LastState = currentState;
currentState = temp;
currentState.EnterState();
}
}
}
private void Update()
{
if (currentState != null)
{
currentState.StateUpdate();
}
}
}