Unity 从零开始的框架搭建1-7 FSM有限状态机与其应用示例

本文小白可能看不懂,所以引路:​​​​​​【最用心 の Unity百宝箱】4. 有限状态机_哔哩哔哩_bilibili

当然,我不是按照小棋这么写的,但是思想都是一样的

另外说句题外话,配合动画状态机的函数用代码去控制逻辑才是真理,大量连线会导致项目无法维护,比如unity商店某Poly FPS PACKAGE里面的动画状态机

目录

1.单例基类

2.Mono代理

3.状态基类

4.状态机类

5.应用


1.单例基类

不懂单例模式?
C# & Unity 设计模式 之 单例模式_unity 使用单例做变量初始化-CSDN博客

cs 复制代码
using UnityEngine;

public class SingltonMono<T> : MonoBehaviour where T : SingltonMono<T>
{
    public static T Instance;
    protected virtual void Awake() 
    {
        if (Instance == null)
        {
            Instance = this as T;
        }
    }
}

2.Mono代理

看不懂Mono代理?

一言蔽之:让没有继承MonoBehaviour的类之中使用 MonoBehaviour 的 生命周期方法等

cs 复制代码
using System;

public class MonoManager : SingltonMono<MonoManager>
{
    private Action UpdateAction;
    private Action LaterUpdateAction;
    private Action FixedUpdateAction;

    public void AddUpdate(Action action)
    {
        UpdateAction += action;
    }

    public void AddLaterUpdate(Action action)
    {
        LaterUpdateAction += action;
    }
    public void AddFixedUpdate(Action action)
    {
        FixedUpdateAction += action;
    }

    public void RemoveUpdate(Action action)
    {
        UpdateAction -= action;
    }
    public void RemoveLaterUpdate(Action action)
    {
        LaterUpdateAction -= action;
    }
    public void RemoveFixedUpdate(Action action)
    {
        FixedUpdateAction -= action;
    }

    private void Update()
    {
        UpdateAction?.Invoke();
    }
    private void LateUpdate()
    {
        LaterUpdateAction?.Invoke();
    }
    private void FixedUpdate()
    {
        FixedUpdateAction?.Invoke();
    }

}

3.状态基类

看不懂状态基类?

我不信你看不懂,这都看不懂就滚去学oop!

C# & Unity 面向对象补全计划 之 初识继承方法与多态(干货)_unity 继承-CSDN博客

cs 复制代码
public abstract class StateBase
{
    public virtual void Init(IStateMachineOwner owner) { }
    public virtual void UnInit() { }
    public virtual void Enter() { }
    public virtual void Exit() { }
    public virtual void Update() { }
    public virtual void LateUpdate() { }
    public virtual void FixedUpdate()
    {
    }
}

4.状态机类

IStateMachineOwner接口利用了里氏替换

C# & Unity 面向对象补全计划 七大原则 之 里氏替换(LSP) 难度:☆☆☆ 总结:子类可以当父类用,牛马是马,骡马也是马-CSDN博客

以及类似控制反转的方式(看下文高级使用实例)

C# & Unity 面向对象补全计划 之 接口_unity c# 接口-CSDN博客

cs 复制代码
using System;
using System.Collections.Generic;

public interface IStateMachineOwner
{
}
public class StateMechine
{
    private IStateMachineOwner owner; //Any Class can be onwner only inherit this interface
    private Dictionary<Type, StateBase> statesDic = new Dictionary<Type, StateBase>();
    public StateBase currentStateBase;

    public Type CurrentStateType => currentStateBase?.GetType();
    public bool HasState => currentStateBase != null;

    //初始化状态机
    public void Init(IStateMachineOwner owner)
    {
        this.owner = owner;
    }
    //切换状态
    public bool ChangeState<T>(bool needRewState = false) where T : StateBase, new()
    {
        //check state is consistent
        if (HasState && CurrentStateType == typeof(T) && !needRewState) return false;

        //exit
        if (currentStateBase != null)
        {
            currentStateBase.Exit();
            MonoManager.Instance.RemoveFixedUpdate(currentStateBase.Update);
            MonoManager.Instance.RemoveLaterUpdate(currentStateBase.LateUpdate);
            MonoManager.Instance.RemoveUpdate(currentStateBase.Update);
        }

        currentStateBase = GetState<T>();
        currentStateBase.Enter();
        MonoManager.Instance.AddUpdate(currentStateBase.Update);
        MonoManager.Instance.AddLaterUpdate(currentStateBase.LateUpdate);
        MonoManager.Instance.AddFixedUpdate(currentStateBase.FixedUpdate);

        return false;
    }
    //获取状态
    public StateBase GetState<T>() where T : StateBase, new()
    {
        if (!statesDic.TryGetValue(typeof(T), out StateBase TryState))
        {
            T t = new T();
            t.Init(owner);
            statesDic.Add(typeof(T), t);
            TryState = t;
        }
        return TryState;
    }
    //停止状态机
    public void Stop()
    {
        currentStateBase.Exit();
        MonoManager.Instance.RemoveUpdate(currentStateBase.Update);
        MonoManager.Instance.RemoveLaterUpdate(currentStateBase.LateUpdate);
        MonoManager.Instance.RemoveFixedUpdate(currentStateBase.FixedUpdate);
        currentStateBase = null;

        foreach (var item in statesDic.Values)
        {
            item.UnInit();
        }
        statesDic.Clear();
    }
}

5.应用

所示工程文件链接如下,因为我比较菜 所以填了一些坑 花了一下午才写这么点功能实在惭愧:

通过网盘分享的文件:Assets.7z链接: https://pan.baidu.com/s/1yqALCXDFgDnb7Trs2181EQ?pwd=1234 提取码: 1234

视频请看这个

状态机应用

我b站好像也发了

分享一下最近的想法_哔哩哔哩_bilibili

相关推荐
Eiceblue1 小时前
使用 C# 将 Excel 转换为 Markdown 表格(含批量转换示例)
开发语言·c#·excel
天人合一peng1 小时前
unity 生成标记根据背景色变色为明显的颜色
unity·游戏引擎
魔士于安2 小时前
Unity 超市总动员 超市收银台 超市货架 超市购物手推车 超市常见商品
游戏·unity·游戏引擎·贴图·模型
CandyU22 小时前
Unity —— 数据持久化
unity·游戏引擎
zh路西法2 小时前
【Unity实现Oneshot胶卷显形】游戏窗口化与Win32API的使用
游戏·unity·游戏引擎
迪捷软件3 小时前
显控系统虚拟仿真的工程化路径
游戏引擎·cocos2d
不会编程的懒洋洋3 小时前
WPF XAML+布局+控件
xml·开发语言·c#·视觉检测·wpf·机器视觉·视图
唐青枫4 小时前
别再层层传参了!C#.NET AsyncLocal 异步上下文透传实战
c#·.net
明如正午5 小时前
【C#】托管调试助手 “PInvokeStackImbalance“:的调用导致堆栈不对称。原因可能是托管的 PInvoke 签名与非托管的目标签名不匹配。
c#
Eiceblue5 小时前
C# 如何实现 Word 转 Excel ?分享两种实用方法
c#·word·excel