Unity进阶--fsm状态机的使用笔记

Unity进阶–fsm状态机的使用笔记

第一种用基础的`if+播放实现动画控制

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yMi6hizN-1689928187185)(QQ%E6%88%AA%E5%9B%BE20230721104017.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vPPZXF2p-1689928187186)(QQ%E6%88%AA%E5%9B%BE20230721104429.png)]

朴实无华,简单易懂,但是耦合性太差。

switch–case实现状态机

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eC0QGMwr-1689928187187)(QQ%E6%88%AA%E5%9B%BE20230721112119.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZckiCoY6-1689928187187)(QQ%E6%88%AA%E5%9B%BE20230721113102.png[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lw462qf8-1689928187417)(QQ%E6%88%AA%E5%9B%BE20230721105058.png)]]

写对应的状态函数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-W5WKaPi9-1689928187188)(QQ%E6%88%AA%E5%9B%BE20230721105520.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1gOBr8KL-1689928187188)(QQ%E6%88%AA%E5%9B%BE20230721105831.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WFChp4VD-1689928187189)(QQ%E6%88%AA%E5%9B%BE20230721105958.png)]

再调用他们,合理,但存在调用问题。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IiVtnGFI-1689928187190)(QQ%E6%88%AA%E5%9B%BE20230721105140.png)]

使用状态机

  • 编写状态基类

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XhC0DwX5-1689928187191)(QQ%E6%88%AA%E5%9B%BE20230721111443.png)]

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public abstract class FSMState
    {
        public int StateID;
        public MonoBehaviour Mono;
        public FSMManager FSMManager;
    
        public FSMState(int stateID, MonoBehaviour mono, FSMManager manager){
            StateID = stateID;
            Mono = mono;
            FSMManager = manager;
        }
        
        public abstract void OnEnter();
    
        public abstract void OnUpdate();
    }
    
    
  • 编写状态机基类

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iWtDGkY3-1689928187191)(QQ%E6%88%AA%E5%9B%BE20230721112301.png)]

    using System.Collections;
    using System.Collections.Generic;
    
    public class FSMManager
    {
       public List<FSMState> StateList = new List<FSMState>();
       public int CurrentIndex = -1;
    
       public void ChangeState(int StateID){
          CurrentIndex = StateID;
          StateList[CurrentIndex].OnEnter(); 
       }
    
       public void Update() {
          if (CurrentIndex != -1){
            StateList[CurrentIndex].OnUpdate();
          }
       }
    }
    
    
  • 编写状态枚举

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4pLOXoXx-1689928187192)(QQ%E6%88%AA%E5%9B%BE20230721112119.png)]

    public enum PlayState
    {
        idle,
        run,
        wave   
    }
    
    
  • 编写几个状态

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Mjlj2KBL-1689928187192)(QQ%E6%88%AA%E5%9B%BE20230721113412.png)]

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class RunState : FSMState
    {
        public RunState(int stateID, MonoBehaviour mono, FSMManager manager) : base(stateID, mono, manager)
        {
        }
    
        public override void OnEnter()
        {
            Mono.GetComponent<Animator>().SetFloat("Speed",5);
        }
    
        public override void OnUpdate()
        {
            float horizontal = Input.GetAxis("Horizontal");
            float vertical = Input.GetAxis("Vertical");
            Vector3 dir = new Vector3(horizontal, 0, vertical);
            if (dir != Vector3.zero){
               Mono.transform.rotation = Quaternion.LookRotation(dir);
               Mono.transform.Translate(Vector3.forward * 5 * Time.deltaTime);
            }
            else {
                FSMManager.ChangeState((int)PlayState.idle);
            }
        }
    }
    
    
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GVXdl8Lg-1689928187192)(../AppData/Roaming/Typora/typora-user-images/image-20230721135226133.png)]

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class IdleState : FSMState
    {
        public IdleState(int stateID, MonoBehaviour mono, FSMManager manager) : base(stateID, mono, manager)
        {
        }
    
        public override void OnEnter()
        {
            Mono.GetComponent<Animator>().SetFloat("Speed",0);
        }
    
        public override void OnUpdate()
        {
            float horizontal = Input.GetAxis("Horizontal");
            float vertical = Input.GetAxis("Vertical");
            Vector3 dir = new Vector3(horizontal, 0, vertical);
            if (dir != Vector3.zero){
               FSMManager.ChangeState((int)PlayState.run);
            }
    
            if (Input.GetKeyDown(KeyCode.Space)){
                Debug.Log("按下空格");
                FSMManager.ChangeState((int)PlayState.wave);
            }
        }
    }
    
    
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wbUcB6cR-1689928187193)(QQ%E6%88%AA%E5%9B%BE20230721113634.png)]

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class WaveState : FSMState
    {
        public WaveState(int stateID, MonoBehaviour mono, FSMManager manager) : base(stateID, mono, manager)
        {
        }
    
        public override void OnEnter()
        {
            Mono.GetComponent<Animator>().SetBool("Rest",true);
        }
    
        public override void OnUpdate()
        {
            if(!Mono.GetComponent<Animator>().GetCurrentAnimatorStateInfo(0).IsName("Rest")){
                FSMManager.ChangeState((int)PlayState.idle);
                Mono.GetComponent<Animator>().SetBool("Rest",false);
            }
        }
    }
    
    
    
    
    • 编写对应的角色控制状态机

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QxsjWa1V-1689928187193)(../AppData/Roaming/Typora/typora-user-images/image-20230721135328692.png)]

      using System.Collections;
      using System.Collections.Generic;
      using UnityEngine;
      
      public class PlayControl : MonoBehaviour
      {
          private FSMManager fSMManager;
          // Start is called before the first frame update
          void Start()
          {
              fSMManager = new FSMManager();
              IdleState idleState = new IdleState(0, this, fSMManager);
              RunState  runState  = new RunState(1, this, fSMManager);
              WaveState waveState = new WaveState(2, this, fSMManager);
      
              fSMManager.StateList.Add(idleState);
              fSMManager.StateList.Add(runState);
              fSMManager.StateList.Add(waveState);
              fSMManager.ChangeState((int)PlayState.idle);
          }
      
          // Update is called once per frame
          void Update()
          {
              fSMManager.Update();
          }
      }
      
      
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值