有限状态机设计
来源:互联网 发布:yy动态头像源码 编辑:程序博客网 时间:2024/05/16 02:41
FSM简介
FSM定义:
一个有限状态机是一个设备,或者是一个设备模型,具有有限数量的状态,它可以在任何给定的时间根据输入进行操作,使得一个状态变换到另一个状态,或者是使一个输入或者一种行为的发生。一个有限状态机在任何瞬间只能处在一种状态。
它的优点:
1.编程快速简单,2.易于调试,3.很少的计算开销,4.直觉性,5.灵活性。
简单的框架
主要的两个类,FSMState表示状态,FSMSystem里面维护了一个状态的列表,最后需要一个StateController作为状态的控制器。
FSMState.cs
using UnityEngine;using System.Collections.Generic;public enum Transition{ NullTransition = 0, // Use this transition to represent a non-existing transition in your system SawPlayer, LostPlayer, NoHealth, ReadytoAim, ReadytoShot, ReadytoIdle, ReadytoAttack, ReadytoChasing}public enum StateID{ NullStateID = 0, // Use this ID to represent a non-existing State in your system Idle, Chasing, // jump Attack, Shooting, Aiming, BacktoIdle,//jump Dead,}public abstract class FSMState{ protected Dictionary<Transition, StateID> map = new Dictionary<Transition, StateID>();// 过度条件<=>状态ID 映射表 protected StateID stateID; // 状态ID public StateID ID { get { return stateID; } } // 只读状态ID public void AddTransition(Transition trans, StateID id) // 添加映射 { // Check if anyone of the args is invalid if (trans == Transition.NullTransition) //返回 { Debug.LogError("FSMState ERROR: NullTransition is not allowed for a real transition"); return; } if (id == StateID.NullStateID) //返回 { Debug.LogError("FSMState ERROR: NullStateID is not allowed for a real ID"); return; } // Since this is a Deterministic FSM, // check if the current transition was already inside the map if (map.ContainsKey(trans)) { Debug.LogError("FSMState ERROR: State " + stateID.ToString() + " already has transition " + trans.ToString() + "Impossible to assign to another state"); return; } map.Add(trans, id); } /// <summary> /// This method deletes a pair transition-state from this state's map. /// If the transition was not inside the state's map, an ERROR message is printed. /// </summary> public void DeleteTransition(Transition trans) // 删除映射 { // Check for NullTransition if (trans == Transition.NullTransition) { Debug.LogError("FSMState ERROR: NullTransition is not allowed"); return; } // Check if the pair is inside the map before deleting if (map.ContainsKey(trans)) { map.Remove(trans); return; } Debug.LogError("FSMState ERROR: Transition " + trans.ToString() + " passed to " + stateID.ToString() + " was not on the state's transition list"); } /// <summary> /// This method returns the new state the FSM should be if /// this state receives a transition and /// </summary> public StateID GetOutputState(Transition trans) // 获取输出状态ID { // Check if the map has this transition if (map.ContainsKey(trans)) { return map[trans]; } return StateID.NullStateID; } /// <summary> /// This method is used to set up the State condition before entering it. /// It is called automatically by the FSMSystem class before assigning it /// to the current state. /// </summary> public virtual void DoBeforeEntering() { } // 进入状态 /// <summary> /// This method is used to make anything necessary, as reseting variables /// before the FSMSystem changes to another one. It is called automatically /// by the FSMSystem before changing to a new state. /// </summary> public virtual void DoBeforeLeaving() { } // 离开状态 /// <summary> /// This method decides if the state should transition to another on its list /// NPC is a reference to the object that is controlled by this class /// </summary> public abstract void Reason(FSMSystem fsms); // 检测 /// <summary> /// This method controls the behavior of the NPC in the game World. /// Every action, movement or communication the NPC does should be placed here /// NPC is a reference to the object that is controlled by this class /// </summary> public abstract void Act(GameObject player = null, GameObject npc = null); // 执行}
FSMSystem.cs
using UnityEngine;using System.Collections.Generic;public class FSMSystem : MonoBehaviour{ private List<FSMState> states; //状态集合 // The only way one can change the state of the FSM is by performing a transition // Don't change the CurrentState directly private StateID currentStateID; //当前状态ID public StateID CurrentStateID { get { return currentStateID; } } private FSMState currentState; //当前状态 public FSMState CurrentState { get { return currentState; } } public StateID defaultState { set { defaultState = value; } get { return defaultState; } } //默认状态ID public void resetToDefaultState() //重置默认 { //currentState = states[0]; //currentStateID = states[0].ID; /*for(int i =0; i< states.Count; i++) { if(states[i].ID == defaultState) { currentState = states[i]; currentStateID = states[i].ID; } }*/ } public FSMSystem() { states = new List<FSMState>(); } /// <summary> /// This method places new states inside the FSM, /// or prints an ERROR message if the state was already inside the List. /// First state added is also the initial state. /// </summary> public void AddState(FSMState s) //增加状态 { // Check for Null reference before deleting if (s == null) { Debug.LogError("FSM ERROR: Null reference is not allowed"); } // First State inserted is also the Initial state, // the state the machine is in when the simulation begins if (states.Count == 0) { states.Add(s); currentState = s; currentStateID = s.ID; return; } // Add the state to the List if it's not inside it foreach (FSMState state in states) { if (state.ID == s.ID) { Debug.LogError("FSM ERROR: Impossible to add state " + s.ID.ToString() + " because state has already been added"); return; } } states.Add(s); } /// <summary> /// This method delete a state from the FSM List if it exists, /// or prints an ERROR message if the state was not on the List. /// </summary> public void DeleteState(StateID id) //删除状态 { // Check for NullState before deleting if (id == StateID.NullStateID) { Debug.LogError("FSM ERROR: NullStateID is not allowed for a real state"); return; } // Search the List and delete the state if it's inside it foreach (FSMState state in states) { if (state.ID == id) { states.Remove(state); return; } } Debug.LogError("FSM ERROR: Impossible to delete state " + id.ToString() + ". It was not on the list of states"); } /// <summary> /// This method tries to change the state the FSM is in based on /// the current state and the transition passed. If current state /// doesn't have a target state for the transition passed, /// an ERROR message is printed. /// </summary> public void PerformTransition(Transition trans) //执行过度状态 { // Check for NullTransition before changing the current state if (trans == Transition.NullTransition) { Debug.LogError("FSM ERROR: NullTransition is not allowed for a real transition"); return; } // Check if the currentState has the transition passed as argument StateID id = currentState.GetOutputState(trans); if (id == StateID.NullStateID) { Debug.LogError("FSM ERROR: State " + currentStateID.ToString() + " does not have a target state " + " for transition " + trans.ToString()); return; } // Update the currentStateID and currentState currentStateID = id; foreach (FSMState state in states) { if (state.ID == currentStateID) { // Do the post processing of the state before setting the new one currentState.DoBeforeLeaving(); currentState = state; // Reset the state to its desired condition before it can reason or act currentState.DoBeforeEntering(); break; } } } // PerformTransition() // void Awake() { FSMState Chasing = new ChasingState(); Chasing.AddTransition(Transition.LostPlayer, StateID.Idle); AddState(Chasing); FSMState Idle = new IdleState(); Idle.AddTransition(Transition.SawPlayer, StateID.Chasing); AddState(Idle); } // void Update() { if (currentState!=null) { currentState.Act(); currentState.Reason(this); } } public bool Chasing = false; public bool Idle = false; void OnGUI() { if (GUI.Button(new Rect(50,50,100,50),"Chasing")) { Chasing = true; Idle = false; } if (GUI.Button(new Rect(50, 150, 100, 50), "Idle")) { Chasing = false; Idle = true; } }}
状态实例
IdleState.cs
using UnityEngine;public class IdleState : FSMState{ public IdleState() { stateID = StateID.Idle; } float time = 0; float timeD = 1; public override void Act(GameObject player = null, GameObject npc = null) { time += Time.deltaTime; if (time > timeD) { time = 0; Debug.Log("@@ IdleState Act"); } } public override void Reason(FSMSystem fsms) { //判断条件 if (fsms.Chasing) { fsms.PerformTransition(Transition.SawPlayer); Debug.Log("@@ IdleState Reason"); } } public override void DoBeforeLeaving() { Debug.Log("@@ IdleState Leaving"); } public override void DoBeforeEntering() { Debug.Log("@@ IdleState Entering"); }}
ChasingState.cs
using UnityEngine;public class ChasingState : FSMState{ public ChasingState() { stateID = StateID.Chasing; } float time = 0; float timeD = 1; public override void Act(GameObject player = null, GameObject npc = null) { time += Time.deltaTime; if (time > timeD) { time = 0; Debug.Log("@@ ChasingState Act"); } } public override void Reason(FSMSystem fsms) { //判断条件 if (fsms.Idle) { fsms.PerformTransition(Transition.LostPlayer); Debug.Log("@@ ChasingState Reason"); } } public override void DoBeforeLeaving() { Debug.Log("@@ ChasingState Leaving"); } public override void DoBeforeEntering() { Debug.Log("@@ ChasingState Entering"); }}
阅读全文
0 0
- 有限状态机设计
- 有限状态机设计
- 有限状态机设计
- 有限状态机的设计思想
- 有限状态机(FSM)设计原理
- verilog语言设计有限状态机习题
- unity3d(C#)的有限状态机设计
- 用STATECAD快速设计有限状态机
- 简单的有限状态机设计---上
- 简单的有限状态机设计---下
- 有限状态机设计 之 流水灯
- FPGA--有限状态机(FSM)的设计
- Verilog HDL 有限状态机的设计
- 设计一个有限状态机及其思路
- 有限状态机
- 有限状态机
- 有限状态机
- 有限状态机
- 利用SVM进行图像目标检测和分类
- 云服务器tomcat部署问题
- 自动化WiFI钓鱼工具——WiFiPhisher源码解读
- Check if Qcom speaker playback algorithms is removed for opalum speaker tuning
- Generator的基本用法
- 有限状态机设计
- 硅谷企业SaaS服务教父:如何衡量与优化SaaS企业的核心指标
- 静态库与动态库的创建与使用
- java日志文件log4j.properties配置详解
- 编程挑战:找一个字符串中最长的单词
- 109. Convert Sorted List to Binary Search Tree
- 页面中文传到后台再传到页面编码
- 机器学习技法课程学习笔记4 -- Soft-Margin Support Vector Machine
- log4j:WARN Please initialize the log4j system properly解决办法