Unity-FSM有限状态机

我们在进行开发时,到了一定程度上,会遇到数十种状态,继续使用Unity的Animator控制器会出现大量的bool,float类型的变量,而这些错综复杂的变量与Animatator控制器如同迷宫版连线相结合会变得极其的复杂且无法良好维护扩展,出现一个BUG会导致开发过程中开发者承受极大的精神力,而这时候,使用有限状态机或者AI行为树便成为了一个极佳的选择,本文只记录了有限状态机的开发使用有限状态机进行状态管理与切换可以大幅度的减少开发时候的难度,在开发过程中只需要关注各个状态间的切换即可

cs 复制代码
public interface IState
{
    //进入状态
    void Enter() { }
    //退出状态
    void Exit() { }
    //状态逻辑更新
    void LogicUpdate() { }
}
cs 复制代码
// <summary>
/// 持有所有状态类,并对他们进行管理和切换
/// 负责当前状态的更新
/// </summary>
public class StateMachine : MonoBehaviour
{
    IState currentState;                                           //当前状态
    public Dictionary<System.Type, IState> stateTable;             //字典,用于保存状态以及查询状态,方便状态切换时                                                                    //进行查找
    public void Update()
    {
        currentState.LogicUpdate();                                //执行每个状态的逻辑切换函数,可以使状态实现检测                                                                    //变换,类似于Update内的函数实时接收信息
    }
    //切换状态
    protected void SwitchOn(IState newState)
    {
        //当前状态变为新状态
        currentState = newState;
        //进入新状态
        currentState.Enter();
    }
    //
    public void SwitchState(IState newState)
    {
        //退出状态
        currentState.Exit();
        //进入新状态
        SwitchOn(newState);
    }
    //切换状态函数重载
    public void SwitchState(System.Type newStateType)
    {
        SwitchState(stateTable[newStateType]);                    //将字典内的状态传入
    }

}
cs 复制代码
public class PlayerState : ScriptableObject, IState
{
    /*************物理检测*************/
    protected bool isGround;                          //是否在地面
    /*************基础信息*************/
    protected bool isRun;                             //是否跑步
    protected bool isJump;                            //是否跳跃
    protected bool isIdle;                            //是否静止
    /*************相关组件*************/
    protected Rigidbody2D my_Body2D;                  //刚体组件,用于获取物体刚体属性
    protected Animator animator;                      //动画组件,用来播放动画
    protected PlayerStateMachine stateMachine;        //PlayerStateMachine,玩家状态机类,执行状态间的切换
    public void Initiatize(Animator animator, Rigidbody2D my_Body2D, PlayerStateMachine stateMachine)
    {//获取PlayerStateMachine传递进来的 动画,刚体,状态机类
        this.animator = animator;
        this.my_Body2D = my_Body2D;
        this.stateMachine = stateMachine;
    }
    public void PhysicalDetection(bool isGround)
    {
        this.isGround = isGround;
    }
    /// <summary>
    /// 状态信息传递
    /// </summary>
    public void BasicInformation(bool isRun,bool isJump,bool isIdle)
    {
        this.isRun = isRun;
        this.isJump = isJump;
        this.isIdle = isIdle;
    }
    //进入状态
    public virtual void Enter() { }
    //离开状态
    public virtual void Exit() { }
    //逻辑切换
    public virtual void LogicUpdate() { }
}
cs 复制代码
/// <summary>
/// 玩家状态机类
/// </summary>
public class PlayerStateMachine : StateMachine
{
    /*************************检测信息***************************/
    PlayerPhysicalDetection playerPhysicalDetection;                      //物理检测组件,这个是继承                                                                                       //MonoBehaviour,挂载到玩家身上来检测                                                                           //玩家的物理信息,例如是否位于地面
    /*************************状态信息***************************/
    //PlayerState资源文件
    [SerializeField] PlayerState[] states;
    Animator animator;                            //获取动画组件
    Rigidbody2D my_Body2D;                        //获取刚体组件
    void Awake()
    {
        /*************************物理检测信息***************************/
        playerPhysicalDetection=GetComponent<PlayerPhysicalDetection>();            //获取物理检测组件

        /*************************状态信息组件***************************/
        stateTable = new Dictionary<System.Type, IState>(states.Length);            //初始化字典
        animator = GetComponent<Animator>();                                        //获取动画组件
        my_Body2D = GetComponent<Rigidbody2D>();                                    //获取刚体组件
        //迭代器循环获取状态
        foreach (PlayerState state in states)
        {
            state.Initiatize(animator, my_Body2D, this);//将动画组件,刚体组件以及PlayerStateMachine传入进去
            //状态存入字典
            stateTable.Add(state.GetType(), state);
        }
    }
    private void Start()
    {//在开始时执行Idle,进入Idle状态
        SwitchOn(stateTable[typeof(PlayerState_Idle)]);
    }
    private new void Update()
    {
        base.Update();//执行父类StateMachine的Update函数
        foreach (PlayerState state in states)
        {//将检测信息传入进去
            state.PhysicalDetection(playerPhysicalDetection.isGround);
            state.BasicInformation( isRun, isJump, isIdle);
        }
    }
}
cs 复制代码
[CreateAssetMenu(menuName = "StateMachine/PlayerState/Idle", fileName = "PlayerState_Idle")]//创建文件
public class PlayerState_Idle : PlayerState
{
    /*****************物理检测*******************/
    public override void Enter()
    {
        //执行该状态数据文件,首先执行进入状态函数,在进入状态函数执行相关的行为
        //进入状态,默认播放Idle动画
        animator.Play("PlayerIdle");
    }
    
    //逻辑切换函数,当检测到处于某种状态,立刻执行该状态的数据文件
    public override void LogicUpdate()
    {
        if(isRun)
        {
            stateMachine.SwitchState(stateMachine.stateTable[typeof(PlayerState_Run)]);
        }
        if(isJump)
        {
            stateMachine.SwitchState(stateMachine.stateTable[typeof(PlayerState_Jump)]);
        }
        if(my_Body2D.velocity.y<0&&!isGround)
        {
            stateMachine.SwitchState(stateMachine.stateTable[typeof(PlayerState_Fall)]);
        }
    }
}
相关推荐
枯萎穿心攻击2 小时前
响应式编程入门教程第二节:构建 ObservableProperty<T> — 封装 ReactiveProperty 的高级用法
开发语言·unity·c#·游戏引擎
X_StarX10 小时前
【Unity笔记02】订阅事件-自动开门
笔记·学习·unity·游戏引擎·游戏开发·大学生
霸王•吕布13 小时前
游戏引擎中顶点着色&像素着色
游戏引擎·顶点着色器·像素着色器·顶点颜色·顶点uv·顶点法向
Thomas_YXQ16 小时前
Unity URP法线贴图实现教程
开发语言·unity·性能优化·游戏引擎·unity3d·贴图·单一职责原则
徐子竣1 天前
[学习记录]Unity-Shader-几何着色器
unity·游戏引擎·着色器
EQ-雪梨蛋花汤1 天前
【Part 3 Unity VR眼镜端播放器开发与优化】第四节|高分辨率VR全景视频播放性能优化
unity·音视频·vr
与火星的孩子对话1 天前
Unity进阶课程【六】Android、ios、Pad 终端设备打包局域网IP调试、USB调试、性能检测、控制台打印日志等、C#
android·unity·ios·c#·ip
幻世界1 天前
【Unity智能模型系列】Unity + MediaPipe + Sentis + ArcFace模型:构建高效人脸识别比对系统
unity·游戏引擎
漫游者Nova2 天前
虚幻引擎Unreal Engine5恐怖游戏设计制作教程,从入门到精通从零开始完整项目开发实战详细讲解中英字幕
ue5·游戏引擎·虚幻·游戏开发完整教程·恐怖游戏开发
死也不注释2 天前
【Unity 编辑器工具开发:GUILayout 与 EditorGUILayout 对比分析】
unity·编辑器·游戏引擎