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

相关推荐
qq_2052790514 分钟前
unity 鼠标更换指定图标
unity·游戏引擎
虾球xz23 分钟前
游戏引擎学习第279天:将实体存储移入世界区块
c++·学习·游戏引擎
虾球xz2 小时前
游戏引擎学习第278天:将实体存储移入世界区块
数据库·c++·学习·游戏引擎
FAREWELL000753 小时前
Unity基础学习(九)输入系统全解析:鼠标、键盘与轴控制
学习·unity·c#·游戏引擎
码观天工4 小时前
【.NET必读】RabbitMQ 4.0+重大变更!C#开发者必须掌握的6大升级要点
c#·rabbitmq·.net·mq
绿龙术士5 小时前
构建现代化WPF应用:数据驱动开发与高级特性解析
c#·wpf
o0向阳而生0o6 小时前
43、Server.UrlEncode、HttpUtility.UrlDecode的区别?
c#·.net
敲代码的 蜡笔小新7 小时前
【行为型之策略模式】游戏开发实战——Unity灵活算法架构的核心实现策略
unity·设计模式·c#·策略模式
Kookoos7 小时前
【实战】基于 ABP vNext 构建高可用 S7 协议采集平台(西门子 PLC 通信全流程)
后端·物联网·c#·.net
钢铁男儿9 小时前
C# 方法(栈帧)
开发语言·c#