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();
          }
      }
      
      

猜你喜欢

转载自blog.csdn.net/abaidaye/article/details/131855094