Finite State Machine (FSM)

Table of contents

1. What is a finite state machine

2. How to achieve

1. Briefly describe the principle

2. Realization


1. What is a finite state machine

A finite state machine is a model used to describe how different states of an object can be converted to each other. The simplest example here is the animation state machine animator. We can only be in one state at a time, and each state can interact with each other through certain conditions. convert.

2. How to achieve

1. Briefly describe the principle

This time we are using ScriptableObject . The idea of ​​implementation is to transition from one state to another. The first thing we can think of is to declare the state and condition separately and then associate the two.

2. Realization

①Preparation : First create the following folders

 ②Specific implementation : Create the following four scripts under the base

using UnityEngine;

public abstract class ContionOS : ScriptableObject
{
    /// <summary>
    /// 判断条件是否成立
    /// </summary>
    /// <returns>bool</returns>
    public abstract bool SetUP();
}
using UnityEngine;

public class stateMachine : MonoBehaviour
{
    public StateOS currentstate;
    public trasitionOS trasitionos;

    private void Awake()
    {
        trasitionos.Init(this);
    }

    private void Update()
    {
        currentstate?.OnUpdate();
        trasitionos.TryGetEnableCondition();//每一帧都查看是否成立
    }

}
using UnityEngine;

public abstract class StateOS : ScriptableObject
{
    public virtual void OnEnter() { }// 新状态进入 虚方法 子类可实现可不实现
    public abstract void OnUpdate(); // 状态更新 抽象方法子类必须实现该方法 不然会报错
    public virtual void OnExit() { } // 状态退出
    
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;

[CreateAssetMenu(fileName ="tranlsationos",menuName ="statemachine/create/tranlasition")]
public class trasitionOS : ScriptableObject
{
    //一个状态转变为其他状态可以有很多个条件 stateOS 状态  ContionOS 条件
    private Dictionary<StateOS, List<ContionOS>> _transition = new Dictionary<StateOS, List<ContionOS>>();

    // 转换列表:用来存储状态和条件的装欢关系
    [SerializeField] private List<translationState> currentState = new List<translationState>();

    //状态机 控制状态的更新
    private stateMachine statemachine; 

    public void Init(stateMachine statemachine)
    {
        this.statemachine = statemachine;
        AddTransition();
    }

    // 当前 状态的条件是否成立
    public void TryGetEnableCondition() 
    {
        if (_transition.ContainsKey(statemachine.currentstate)) 
        {
            foreach (var item in _transition[statemachine.currentstate])
            {
                if (item.SetUP()) 
                {
                    translatinon(item);
                }
            }
        }
    }
    /// <summary>
    /// 切换状态
    /// </summary>
    /// <param name="condition">当前状态的条件</param>
    public void translatinon(ContionOS condition) 
    {
        statemachine.currentstate?.OnExit();
        statemachine.currentstate = GetNextstate(condition);
        statemachine.currentstate?.OnEnter();
    }

    public StateOS GetNextstate(ContionOS condition) 
    {
        foreach (var item in currentState)
        {
            if (item.condition == condition && statemachine.currentstate == item.fromState) 
            {
                return item.toState;
            }
        }
        return null;
    }

    /// <summary>
    /// 将状态和条件加入到装欢列表
    /// </summary>
    public void AddTransition() 
    {
        if (currentState.Count != 0) 
        {
            foreach (var item in currentState)
            {
                if (!_transition.ContainsKey(item.fromState))
                {
                    _transition.Add(item.fromState, new List<ContionOS>());
                    _transition[item.fromState].Add(item.condition);
                    Debug.Log("创建并添加");
                }
                else 
                {
                    if (_transition[item.fromState].Contains(item.condition)) 
                    {
                        _transition[item.fromState].Add(item.condition);
                        Debug.Log("存在并再次添加条件");
                    }
                }
            }
        }

    }

    [Serializable]
    private class translationState
    {
        public StateOS fromState;
        public StateOS toState;
        public ContionOS condition;

        private  translationState(StateOS fromState, StateOS toState, ContionOS condition) 
        {
            this.fromState = fromState;
            this.toState = toState;
            this.condition = condition;
        }
        
    }
}

③Test : Hang the stateMachine script on the object, create the following script and create a ScriptableObject based on the script

Examples and tranlsasitions examples

 


[CreateAssetMenu(fileName = "condition_idel", menuName = "statemachine/create/Condition/condition_idel")]
public class condition_idel: ContionOS
{
    public override bool SetUP()
    {
        return true;
    }
}
[CreateAssetMenu(fileName = "condition_walk", menuName = "statemachine/create/Condition/condition_walk")]
public class condition_walk : ContionOS
{
    public override bool SetUP()
    {
        return Input.GetKeyDown(KeyCode.W);
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(fileName = "idel", menuName = "statemachine/create/stateos/idel")]
public class idel : StateOS
{
    public override void OnUpdate()
    {
        Debug.Log("正处于idel");
    }
    public override void OnEnter()
    {
        Debug.Log("进入idel");
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(fileName = "walk", menuName = "statemachine/create/stateos/walk")]
public class walk : StateOS
{
    public override void OnUpdate()
    {
        Debug.Log("正处于walk");
    }
    public override void OnEnter()
    {
        Debug.Log("进入walk");
    }
}

Create the corresponding instance according to the path, and perform the following operations on the created instance

 

 

This is just a basic fsm and can be extended.

Guess you like

Origin blog.csdn.net/m0_52021450/article/details/127641593