FSM (Finite State Machine)

FSM

Although Unity already has an animation state machine, for the principle of open and closed code, the role of the FSM finite state machine is highlighted at this time.

Create a script that controls the finite state machine

First create a script to control the finite state machine (FSM), mainly for switching states.
First use an enumeration to list each state

public enum StateType
{
    
    
    ldle,
    run,
    jumping,
    dying,
    shooting
}

Then we need a container to save the current state, store it in a dictionary to facilitate subsequent changes to the next state and then initialize the class, create the dictionary, and add two methods to increase and set the state, and finally execute it every frame. code show as below

  //当前在运行什么状态
    private State currentState;
    public StateType stateType;//各个状态的标识符
    //写一个保存所有状态的容器
    private Dictionary<StateType, State> allSaveState;

    public FSMControl()
    {
    
    
        allSaveState = new Dictionary<StateType, State>();
    }

    public void OnTick()//每一帧执行一次
    {
    
    
        currentState?.OnUpdate();
    }
    public void AddState(StateType stateType, State state)
    {
    
    
        if (allSaveState.ContainsKey(stateType))
            return;
        allSaveState.Add(stateType, state);
        
    }
    public void SetState(StateType stateType)//我们需要传一个参数,告诉状态机需要切换到哪一个状态中去
    {
    
    
        if (currentState == allSaveState[stateType]) return;//判断当前状态是否重复
        currentState?.OnEnter();//判断当前状态是否为空
        currentState = allSaveState[stateType];
        currentState.OnEnter();
    }

The complete code is as follows

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public enum StateType
{
    
    
    ldle,
    run,
    jumping,
    dying,
    shooting
}
public class FSMControl
{
    
    
    //当前在运行什么状态
    private State currentState;
    public StateType stateType;//各个状态的标识符
    //写一个保存所有状态的容器
    private Dictionary<StateType, State> allSaveState;

    public FSMControl()
    {
    
    
        allSaveState = new Dictionary<StateType, State>();
    }

    public void OnTick()//每一帧执行一次
    {
    
    
        currentState?.OnUpdate();
    }
    public void AddState(StateType stateType, State state)
    {
    
    
        if (allSaveState.ContainsKey(stateType))
            return;
        allSaveState.Add(stateType, state);
        
    }
    public void SetState(StateType stateType)//我们需要传一个参数,告诉状态机需要切换到哪一个状态中去
    {
    
    
        if (currentState == allSaveState[stateType]) return;//判断当前状态是否重复
        currentState?.OnEnter();//判断当前状态是否为空
        currentState = allSaveState[stateType];
        currentState.OnEnter();
    }






}

Set each state under the FSM state machine

Next, one of the states will be shown, and other states can be written by analogy

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public  class ldle: State
{
    
    
    private Animator animator;
    private float deltaTime = 5f;
    private FSMControl fsm;
    public ldle(Animator animator,FSMControl fsm)
    {
    
    
        this.animator = animator;
        this.fsm = fsm;
    }
//刚刚进入状态时的行为
    public override void OnEnter()
    {
    
    
        Debug.Log("闲");
    }
//正在进行状态时的行为
    public override void OnUpdate()
    {
    
    
        Debug.Log("站着吧");
        if (deltaTime >= 0)
        {
    
    
            deltaTime -= Time.deltaTime;
            if (deltaTime<0)
            {
    
    
                fsm.SetState((StateType.run));//更改状态为跑
            }
        }
    }
//退出状态后的行为
    public override void OnExit()
    {
    
    
        Debug.Log("该动起来了");
    }
}

You can change the conditions for switching states according to your own conditions. Here I set the state to run after 5 seconds

Add test class

But after we finish writing the first two scripts, we can add the test class, that is, after adding various states and setting the initial state, it can run normally

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TestFSM : MonoBehaviour
{
    
    
    private FSMControl fsm;
    private StateType stateType;
    private Animator animator;

    private void Awake()
    {
    
    
        fsm = new FSMControl();
        animator = GetComponentInChildren<Animator>();

        fsm.AddState(StateType.ldle, new ldle(animator,this.fsm));
        fsm.AddState(StateType.run, new run(animator));
        fsm.SetState(StateType.ldle);
    }
    private void Update()
    {
    
    
        fsm.OnTick();
    }
}

Advantages of FSMs

When you need a new state, you can directly set the script to inherit FSMControl, which ensures the principle of open and closed code. If you use the animation state machine switch, you need to directly change the original code. Using FSM, you can directly create a new script to achieve the increase. other status

Guess you like

Origin blog.csdn.net/tongmeng_yiran/article/details/129221073