• unity之通用FSM有限状态机(一)


    什么是有限状态机:

    有限状态机是一种用来进行对象行为建模的工具,作用是描述对象在它的生命周期内所经历的状态序列,以及如何响应来自外界的各种事件。简单理解就是:状态满足条件下的一种处理机制。

    有限状态机,任意时刻都处于有限状态集合中的某一状态。当获得一个输入字符时,将从当前状态转换到另一状态或仍保持当前状态。

    每一个状态都有三种行为:进入、 执行、 离开。

     

    对状态机有一个简单的了解之后,那么状态机在unity游戏开发中有哪些应用呢?

    大多游戏都有以下流程:

    这些流程,我们是不是可以理解为状态。

    在AI 方面,游戏中的玩家行为大致有以下状态:

    站立(待机)、跑、跳、普攻、技能1,技能2,技能3,受伤、控制(眩晕、禁锢)、死亡 等等

     

    以上2种举例都可体现有限状态机在游戏中的应用。故设计通用的状态机就显得很有必要。而不是为每一个应用都写一个状态机。

     

    废话不多说,直接上代码

    状态机基类:

     1 public abstract class TestFsmBase
     2 {
     3     /// <summary>
     4     /// 状态机编号
     5     /// </summary>
     6     public int FsmId { get; private set; }
     7 
     8     /// <summary>
     9     /// 状态机当前的状态
    10     /// </summary>
    11     public sbyte CurrState;
    12 
    13 
    14     public TestFsmBase(int fsmId)
    15     {
    16         FsmId = fsmId;
    17     }
    18 
    19     /// <summary>
    20     /// 关闭
    21     /// </summary>
    22     public abstract void ShutDown();
    23 }

     

    状态机状态

     1 public class TestFsmState<T> where T : class
     2 {
     3     public TestFsm<T> CurrFsm;
     4 
     5     public virtual void OnEnter()
     6     {
     7     }
     8 
     9     public virtual void OnUpdate()
    10     {
    11     }
    12 
    13     public virtual void OnLeave()
    14     {
    15     }
    16 
    17     public virtual void OnDestroy()
    18     {
    19 
    20     }
    21 }

     

    状态机:

     1 using System.Collections.Generic;
     2 
     3 public class TestFsm<T> : TestFsmBase where T : class
     4 {
     5     /// <summary>
     6     /// 状态机拥有者
     7     /// </summary>
     8     public T Owner { get; private set; }
     9 
    10     public TestFsmState<T> m_CurrFsmState;
    11 
    12     public Dictionary<sbyte, TestFsmState<T>> m_StateDic;
    13 
    14 
    15     public TestFsm(int fsmId, T owner, TestFsmState<T>[] status) : base(fsmId)
    16     {
    17         Owner = owner;
    18         m_StateDic = new Dictionary<sbyte, TestFsmState<T>>();
    19         for (int i = 0; i < status.Length; i++)
    20         {
    21             m_StateDic[(sbyte)i] = status[i];
    22             status[i].CurrFsm = this;//状态的状态机就是Fsm本身
    23         }
    24         CurrState = -1;
    25     }
    26 
    27     /// <summary>
    28     /// 获取状态
    29     /// </summary>
    30     /// <returns></returns>
    31     public TestFsmState<T> GetState(sbyte stateType)
    32     {
    33         m_StateDic.TryGetValue(stateType, out TestFsmState<T> fsmState);
    34         return fsmState;
    35     }
    36 
    37     /// <summary>
    38     /// 切换状态
    39     /// </summary>
    40     /// <param name="newState"></param>
    41     public void ChangeState(sbyte newState)
    42     {
    43         //上一个状态离开 新状态进入
    44         if (newState == CurrStateType) return;
    45         if (m_CurrFsmState != null)
    46         {
    47             m_CurrFsmState.OnLeave();
    48         }
    49         if (m_StateDic.TryGetValue(newState, out TestFsmState<T> newFsmState))
    50         {
    51             CurrState = newState;
    52             m_CurrFsmState = newFsmState;
    53             m_CurrFsmState.OnEnter();
    54         }
    55     }
    56 
    57     public void OnUpdate()
    58     {
    59         if (m_CurrFsmState != null)
    60         {
    61             m_CurrFsmState.OnUpdate();
    62         }
    63     }
    64 
    65     /// <summary>
    66     /// 关闭状态机
    67     /// </summary>
    68     public override void ShutDown()
    69     {
    70         if (m_CurrFsmState != null)
    71         {
    72             m_CurrFsmState.OnLeave();
    73         }
    74         var enumerator = m_StateDic.GetEnumerator();
    75         while (enumerator.MoveNext())
    76         {
    77             enumerator.Current.Value.OnDestroy();
    78         }
    79         m_StateDic.Clear();
    80     }
    81 }

     

    状态机管理器:

     1 using System;
     2 using System.Collections.Generic;
     3 
     4 /// <summary>
     5 /// 状态机管理器
     6 /// </summary>
     7 public class TestFsmManager : IDisposable
     8 {
     9     private int m_tempFsmId = 1;
    10     private readonly Dictionary<int, TestFsmBase> fmsDic;
    11 
    12     public TestFsmManager()
    13     {
    14         fmsDic = new Dictionary<int, TestFsmBase>();
    15     }
    16 
    17     /// <summary>
    18     /// 创建
    19     /// </summary>
    20     /// <typeparam name="T"></typeparam>
    21     /// <param name="own"></param>
    22     /// <param name="status"></param>
    23     /// <returns></returns>
    24     public TestFsm<T> CreateFsm<T>(T owner, TestFsmState<T>[] status) where T : class
    25     {
    26         TestFsm<T> fsm = new TestFsm<T>(m_tempFsmId++, owner, status);
    27         fmsDic[m_tempFsmId] = fsm;
    28         return fsm;
    29     }
    30 
    31     /// <summary>
    32     /// 是否存在
    33     /// </summary>
    34     /// <param name="fsmId"></param>
    35     /// <returns></returns>
    36     public bool HasFsm(int fsmId)
    37     {
    38         return fmsDic.ContainsKey(fsmId);
    39     }
    40 
    41     /// <summary>
    42     /// 销毁
    43     /// </summary>
    44     /// <param name="fsmId"></param>
    45     public void DestroyFsm(int fsmId)
    46     {
    47         if (fmsDic.TryGetValue(fsmId, out TestFsmBase fsmBase))
    48         {
    49             fsmBase.ShutDown();
    50             fmsDic.Remove(fsmId);
    51         }
    52     }
    53 
    54     public void Dispose()
    55     {
    56         var enumerator = fmsDic.GetEnumerator();
    57         while (enumerator.MoveNext())
    58         {
    59             enumerator.Current.Value.ShutDown();
    60         }
    61         fmsDic.Clear();
    62     }
    63 }

     

    接下来,讲解下状态机在流程应用方面是如何使用的。

  • 相关阅读:
    学生管理系统后感
    数据库是什么鬼,怎么连接,怎么搞
    nIce 不看会后悔的o!
    那些年披巾斩浪的数据库
    day82
    day81
    day80
    day79
    day78
    day77
  • 原文地址:https://www.cnblogs.com/zhaolaosan/p/15841433.html
Copyright © 2020-2023  润新知