unity 有限状态机(一)

来源:互联网 发布:域名被腾讯浏览器拦截 编辑:程序博客网 时间:2024/05/16 09:17

原文链接:http://wiki.unity3d.com/index.php/Finite_State_Machine

出于学习目的,修改了部分注释和调试输出等内容,版权归原文所有,仅供大家学习使用。

状态机很万能的样子,但是容易被乱用,反而增加工程的复杂度,尤其是这种复杂状态机的实现方式。

所有状态继承FSMState,然后在updet中使用FSMsys。

FSMSystem.cs

[csharp] view plain copy
  1. using System;  
  2. using System.Collections;  
  3. using System.Collections.Generic;  
  4. using UnityEngine;  
  5.    
  6.   
  7. // 状态转换  
  8. public enum Transition  
  9. {  
  10.     NullTransition = 0, // 系统中不存在转换  
  11.     // 需要根据实际应用继续扩展  
  12. }  
  13.   
  14. // 状态ID  
  15. public enum StateID  
  16. {  
  17.     NullStateID = 0,    // 系统中不存在状态  
  18.     PlayerMove = 2,     // 玩家战斗移动状态  
  19.     PlayerAttack = 4,   // 玩家战斗攻击状态  
  20.     EnemyMove = 6,      // 敌人战斗移动状态  
  21.     EnemyAttack = 8,    // 敌人战斗攻击状态  
  22.   
  23. }  
  24.   
  25. // 转换信息类:  
  26. public class TransInfo  
  27. {  
  28.     public string comment;  
  29. }  
  30.   
  31. /// <summary>  
  32. /// 状态机中的状态类:以字典的形式保存状态的转换  
  33. /// 1. Reason() 决定触发哪个转换  
  34. /// 2. Act() 决定NPC在当前状态下的行为  
  35. /// </summary>  
  36. public abstract class FSMState  
  37. {  
  38.     protected Dictionary<Transition, StateID> map = new Dictionary<Transition, StateID>();  // 状态转换映射  
  39.     protected StateID stateID;                     // 状态ID  
  40.     public StateID ID { get { return stateID; } }  // 获取当前状态ID  
  41.   
  42.     /// 添加转换  
  43.     public void AddTransition(Transition trans, StateID id)  
  44.     {  
  45.         // 空值检验  
  46.         if (trans == Transition.NullTransition)  
  47.         {  
  48.             Debug.LogError("FSMState ERROR: 不能添加空转换");  
  49.             return;  
  50.         }  
  51.   
  52.         if (id == StateID.NullStateID)  
  53.         {  
  54.             Debug.LogError("FSMState ERROR: 不能添加空状态");  
  55.             return;  
  56.         }  
  57.   
  58.         // 检查是否已经有该转换  
  59.         if (map.ContainsKey(trans))  
  60.         {  
  61.             Debug.LogError("FSMState ERROR: 状态 " + stateID.ToString() + " 已经包含转换 " + trans.ToString() + "不可添加另一个状态");  
  62.             return;  
  63.         }  
  64.   
  65.         map.Add(trans, id);  
  66.     }  
  67.   
  68.     /// 删除状态转换  
  69.     public void DeleteTransition(Transition trans)  
  70.     {  
  71.         // 空值检验  
  72.         if (trans == Transition.NullTransition)  
  73.         {  
  74.             Debug.LogError("FSMState ERROR: 不能删除空转换");  
  75.             return;  
  76.         }  
  77.   
  78.         // 检验是否有配对的转换  
  79.         if (map.ContainsKey(trans))  
  80.         {  
  81.             map.Remove(trans);  
  82.             return;  
  83.         }  
  84.         Debug.LogError("FSMState ERROR: 转换 " + trans.ToString() + " - 状态 " + stateID.ToString() +  " 不存在");  
  85.     }  
  86.   
  87.     /// 获取下一个状态  
  88.     public StateID GetOutputState(Transition trans)  
  89.     {  
  90.         // 如果存在转换,返回对应状态  
  91.         if (map.ContainsKey(trans))  
  92.         {  
  93.             return map[trans];  
  94.         }  
  95.         return StateID.NullStateID;  
  96.     }  
  97.   
  98.     /// 进入状态之前执行  
  99.     public virtual void DoBeforeEntering() { }  
  100.   
  101.     /// 离开状态之前执行  
  102.     public virtual void DoBeforeLeaving() { }  
  103.   
  104.     /// 状态转换条件  
  105.     public abstract void Reason(GameObject player, GameObject npc);  
  106.   
  107.     /// 控制行为  
  108.     public abstract void Act(GameObject player, GameObject npc);  
  109.   
  110. }   
  111.   
  112. /// <summary>  
  113. /// 状态机类:包含状态列表  
  114. /// 1. 删除状态  
  115. /// 2. 改变当前状态  
  116. /// </summary>  
  117. public class FSMSystem  
  118. {  
  119.     private List<FSMState> states;  // 状态列表  
  120.   
  121.     // 在状态机中改变当前状态的唯一途径是通过转换,当前状态不可直接改变  
  122.     private StateID currentStateID;  
  123.     public StateID CurrentStateID { get { return currentStateID; } }  
  124.     private FSMState currentState;  
  125.     public FSMState CurrentState { get { return currentState; } }  
  126.   
  127.     public FSMSystem()  
  128.     {  
  129.         states = new List<FSMState>();  
  130.     }  
  131.   
  132.     /// 添加状态  
  133.     public void AddState(FSMState s)  
  134.     {  
  135.         // 空值检验  
  136.         if (s == null)  
  137.         {  
  138.             Debug.LogError("FSM ERROR: 不可添加空状态");  
  139.         }  
  140.   
  141.         // 当所添加状态为初始状态  
  142.         if (states.Count == 0)  
  143.         {  
  144.             states.Add(s);  
  145.             currentState = s;  
  146.             currentStateID = s.ID;  
  147.             return;  
  148.         }  
  149.   
  150.         // 遍历状态列表,若不存在该状态,则添加  
  151.         foreach (FSMState state in states)  
  152.         {  
  153.             if (state.ID == s.ID)  
  154.             {  
  155.                 Debug.LogError("FSM ERROR: 无法添加状态 " + s.ID.ToString() + " 因为该状态已存在");  
  156.                 return;  
  157.             }  
  158.         }  
  159.         states.Add(s);  
  160.     }  
  161.   
  162.     /// 删除状态  
  163.     public void DeleteState(StateID id)  
  164.     {  
  165.         // 空值检验  
  166.         if (id == StateID.NullStateID)  
  167.         {  
  168.             Debug.LogError("FSM ERROR: 状态ID 不可为空ID");  
  169.             return;  
  170.         }  
  171.   
  172.         // 遍历并删除状态  
  173.         foreach (FSMState state in states)  
  174.         {  
  175.             if (state.ID == id)  
  176.             {  
  177.                 states.Remove(state);  
  178.                 return;  
  179.             }  
  180.         }  
  181.         Debug.LogError("FSM ERROR: 无法删除状态 " + id.ToString() + ". 状态列表中不存在");  
  182.     }  
  183.   
  184.     /// 执行转换  
  185.     public void PerformTransition(Transition trans)  
  186.     {  
  187.         // 空值检验  
  188.         if (trans == Transition.NullTransition)  
  189.         {  
  190.             Debug.LogError("FSM ERROR: 转换不可为空");  
  191.             return;  
  192.         }  
  193.   
  194.         // 获取当前状态ID  
  195.         StateID id = currentState.GetOutputState(trans);  
  196.         if (id == StateID.NullStateID)  
  197.         {  
  198.             Debug.LogError("FSM ERROR: 状态 " + currentStateID.ToString() + " 不存在目标状态 " +  
  199.                            " - 转换: " + trans.ToString());  
  200.             return;  
  201.         }  
  202.   
  203.         // 更新当前状态ID 与 当前状态        
  204.         currentStateID = id;  
  205.         foreach (FSMState state in states)  
  206.         {  
  207.             if (state.ID == currentStateID)  
  208.             {  
  209.                 // 执行当前状态后处理  
  210.                 currentState.DoBeforeLeaving();  
  211.   
  212.                 currentState = state;  
  213.   
  214.                 // 执行当前状态前处理  
  215.                 currentState.DoBeforeEntering();  
  216.                 break;  
  217.             }  
  218.         }  
  219.     }   
  220. }


0 0
原创粉丝点击