Unity 一个比较适合学习的FSM状态机(汉化和功能简述)

server/2024/10/18 6:05:37/

        该轮子由网络资源而来,遵从作者开源意愿,仅作免费学习和分享,不作任何商业行为 ,本文不支持任何交易行为,侵权删!!!

        至于我为什么不将此文章设置为转载,是因为该代码所在的网站早在2020年前就已经关闭了,也就是该资源是祖传的,很有意思吧

 1.总览

请无视枚举中多出来的内容

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;/**
基于 Eric Dybsand 在《Game Programming Gems 1》第3.1章中的有限状态机系统作者:Roberto Cezar Bianchini,2010年7月使用方法:1. 在相应的枚举中放置有限状态系统的转换和状态标签。2. 编写继承自 FSMState 的新类,并在每个类中填充(转换-状态)对。这些对表示当 FSMSystem 处于状态 S1 时,如果触发了转换 T,且状态 S1 有从 T 到 S2 的转换,FSMSystem 应该处于状态 S2。请记住,这是一个确定性 FSM。一个转换不能导致两个不同的状态。方法 Reason 用于确定应该触发哪个转换。你可以在其他地方编写触发转换的代码,并将此方法留空,如果你觉得这更适合你的项目。方法 Act 包含 NPC 在此状态下应该执行的动作代码。你可以在其他地方编写动作代码,并将此方法留空,如果你觉得这更适合你的项目。3. 创建 FSMSystem 类的实例,并添加状态。4. 从你的 Update 或 FixedUpdate 方法中调用 Reason 和 Act(或你用于触发转换和使 NPC 在游戏中表现的任何方法)。Unity 引擎的异步转换,如 OnTriggerEnter、SendMessage,也可以使用,只需在事件发生时从你的 FSMSystem 实例中调用 PerformTransition 方法,并传入正确的转换。软件按“原样”提供,不提供任何形式的明示或暗示担保,
包括但不限于适销性、特定用途适用性和非侵权的担保。
在任何情况下,作者或版权持有人均不对任何索赔、损害或其他责任负责,
无论是在合同诉讼、侵权行为或其他情况下,
由软件或软件使用或其他交易引起或与之相关。
*//// <summary>
/// 在这个枚举中放置转换的标签。
/// 不要更改第一个标签 NullTransition,因为 FSMSystem 类使用它。
/// </summary>
public enum Transition {NullTransition = 0, // 使用这个转换来表示系统中不存在的转换StartButtonClick,PauseButtonClick
}/// <summary>
/// 在这个枚举中放置状态的标签。
/// 不要更改第一个标签 NullStateID,因为 FSMSystem 类使用它。
/// </summary>
public enum StateID {NullStateID = 0, // 使用这个 ID 来表示系统中不存在的状态Menu,Play,Pause,GameOver
}/// <summary>
/// 这个类代表有限状态系统中的状态。
/// 每个状态都有一个包含(转换-状态)对的字典,
/// 显示当这个状态是当前状态时,如果触发了转换,
/// FSM 应该处于哪个状态。
/// 方法 Reason 用于确定应该触发哪个转换。
/// 方法 Act 包含 NPC 在这个状态下应该执行的动作代码。
/// </summary>
public abstract class FSMState : MonoBehaviour {protected Ctrl ctrl;public Ctrl CTRL {set {ctrl = value;}}protected FSMSystem fsm;public FSMSystem FSM {set {fsm = value;}}protected Dictionary<Transition, StateID> map = new Dictionary<Transition, StateID>();protected StateID stateID;public StateID ID {get {return stateID;}}public void AddTransition(Transition trans, StateID id) {// 检查参数是否无效if (trans == Transition.NullTransition) {Debug.LogError("FSMState 错误:NullTransition 不允许作为真实的转换");return;}if (id == StateID.NullStateID) {Debug.LogError("FSMState 错误:NullStateID 不允许作为真实的 ID");return;}// 由于这是一个确定性 FSM,// 检查当前转换是否已经在字典中if (map.ContainsKey(trans)) {Debug.LogError("FSMState 错误:状态 " + stateID.ToString() + " 已经有转换 " + trans.ToString() +"无法分配给另一个状态");return;}map.Add(trans, id);}/// <summary>/// 这个方法从该状态的映射中删除一个转换-状态对。/// 如果转换不在该状态的映射中,将打印错误信息。/// </summary>public void DeleteTransition(Transition trans) {// 检查 NullTransitionif (trans == Transition.NullTransition) {Debug.LogError("FSMState 错误:不允许使用 NullTransition");return;}// 在删除之前检查该对是否在映射中if (map.ContainsKey(trans)) {map.Remove(trans);return;}Debug.LogError("FSMState 错误:传递给 " + stateID.ToString() + " 的转换 " + trans.ToString() +" 不在该状态的转换列表中");}/// <summary>/// 如果这个状态接收到一个转换,这个方法返回 FSM 应该处于的新状态/// </summary>public StateID GetOutputState(Transition trans) {// 检查映射中是否有这个转换if (map.ContainsKey(trans)) {return map[trans];}return StateID.NullStateID;}/// <summary>/// 这个方法用于在进入状态之前设置状态条件。/// 它在 FSMSystem 类将其分配为当前状态之前自动调用。/// </summary>public virtual void DoBeforeEntering() {}/// <summary>/// 这个方法用于在 FSMSystem 切换到另一个状态之前,/// 执行任何必要的操作,如重置变量。/// 它在 FSMSystem 切换到新状态之前自动调用。/// </summary>public virtual void DoBeforeLeaving() {}/// <summary>/// 这个方法决定状态是否应该转换到其列表中的另一个状态。/// NPC 是一个引用,指向由这个类控制的对象。/// </summary>public virtual void Reason() {}/// <summary>/// 这个方法控制 NPC 在游戏世界中的行为。/// NPC 执行的每个动作、移动或交流都应该放在这里。/// NPC 是一个引用,指向由这个类控制的对象。/// </summary>public virtual void Act() {}} // class FSMState/// <summary>
/// FSMSystem 类代表有限状态机类。
/// 它有一个包含 NPC 状态的列表和添加、删除状态以及更改当前状态的方法。
/// </summary>
public class FSMSystem {private List<FSMState> states;// 改变 FSM 状态的唯一方法是执行转换// 不要直接更改 CurrentStateprivate StateID currentStateID;public StateID CurrentStateID {get {return currentStateID;}}private FSMState currentState;public FSMState CurrentState {get {return currentState;}}public FSMSystem() {states = new List<FSMState>();}public void SetCurrentState(FSMState s) {currentState = s;currentStateID = s.ID;s.DoBeforeEntering();}/// <summary>/// 这个方法将新状态放入 FSM 中,/// 如果状态已经在列表中,则打印错误信息。/// 添加的第一个状态也是初始状态。/// </summary>public void AddState(FSMState s, Ctrl ctrl) {// 在删除之前检查空引用if (s == null) {Debug.LogError("FSM 错误:不允许空引用");}s.FSM = this;s.CTRL = ctrl;// 插入的第一个状态也是初始状态,// 模拟开始时机器所处的状态if (states.Count == 0) {states.Add(s);return;}// 如果状态不在列表中,则将其添加到列表中foreach (FSMState state in states) {if (state.ID == s.ID) {Debug.LogError("FSM 错误:无法添加状态 " + s.ID.ToString() +" 因为状态已经被添加");return;}}states.Add(s);}/// <summary>/// 如果状态存在,这个方法从 FSM 列表中删除一个状态,/// 如果状态不在列表中,则打印错误信息。/// </summary>public void DeleteState(StateID id) {// 在删除之前检查 NullStateif (id == StateID.NullStateID) {Debug.LogError("FSM 错误:不允许使用 NullStateID 作为真实状态");return;}// 搜索列表并删除其中的状态foreach (FSMState state in states) {if (state.ID == id) {states.Remove(state);return;}}Debug.LogError("FSM 错误:无法删除状态 " + id.ToString() +"。它不在状态列表中");}/// <summary>/// 这个方法尝试根据当前状态和传递的转换来改变 FSM 所处的状态。/// 如果当前状态没有传递的转换的目标状态,则打印错误信息。/// </summary>public void PerformTransition(Transition trans) {// 在更改当前状态之前检查 NullTransitionif (trans == Transition.NullTransition) {Debug.LogError("FSM 错误:不允许使用 NullTransition 作为真实转换");return;}// 检查当前状态是否有传递的转换StateID id = currentState.GetOutputState(trans);if (id == StateID.NullStateID) {Debug.LogError("FSM 错误:状态 " + currentStateID.ToString() + " 没有目标状态 " +" 对于转换 " + trans.ToString());return;}// 更新 currentStateID 和 currentStatecurrentStateID = id;foreach (FSMState state in states) {if (state.ID == currentStateID) {// 在设置新状态之前进行状态的后处理currentState.DoBeforeLeaving();currentState = state;// 在状态可以推理或行动之前重置其到所需条件currentState.DoBeforeEntering();break;}}} // PerformTransition()} //class FSMSystem

2.功能分述 

        功能:定义了状态转换的标签。NullTransition 用于表示不存在的转换。

public enum Transition
{NullTransition = 0, // 使用这个转换来表示系统中不存在的转换StartButtonClick,PauseButtonClick
}

        功能:定义了状态的标签。NullStateID 用于表示不存在的状态。

public enum StateID
{NullStateID = 0, // 使用这个 ID 来表示系统中不存在的状态Menu,Play,Pause,GameOver
}

        功能

  • AddTransition:添加状态转换。
  • DeleteTransition:删除状态转换。
  • GetOutputState:获取转换后的状态。
  • DoBeforeEntering:进入状态前的设置。
  • DoBeforeLeaving:离开状态前的设置。
  • Reason:决定是否进行状态转换。
  • Act:控制 NPC 在当前状态下的行为。
  • public abstract class FSMState : MonoBehaviour
    {protected Ctrl ctrl;public Ctrl CTRL { set { ctrl = value; } }protected FSMSystem fsm;public FSMSystem FSM { set { fsm = value; } }protected Dictionary<Transition, StateID> map = new Dictionary<Transition, StateID>();protected StateID stateID;public StateID ID { get { return stateID; } }public void AddTransition(Transition trans, StateID id){// 检查参数是否无效if (trans == Transition.NullTransition){Debug.LogError("FSMState 错误:NullTransition 不允许作为真实的转换");return;}if (id == StateID.NullStateID){Debug.LogError("FSMState 错误:NullStateID 不允许作为真实的 ID");return;}// 检查当前转换是否已经在字典中if (map.ContainsKey(trans)){Debug.LogError("FSMState 错误:状态 " + stateID.ToString() + " 已经有转换 " + trans.ToString() +"无法分配给另一个状态");return;}map.Add(trans, id);}public void DeleteTransition(Transition trans){// 检查 NullTransitionif (trans == Transition.NullTransition){Debug.LogError("FSMState 错误:不允许使用 NullTransition");return;}// 在删除之前检查该对是否在映射中if (map.ContainsKey(trans)){map.Remove(trans);return;}Debug.LogError("FSMState 错误:传递给 " + stateID.ToString() + " 的转换 " + trans.ToString() +" 不在该状态的转换列表中");}public StateID GetOutputState(Transition trans){// 检查映射中是否有这个转换if (map.ContainsKey(trans)){return map[trans];}return StateID.NullStateID;}public virtual void DoBeforeEntering() { }public virtual void DoBeforeLeaving() { }public virtual void Reason() { }public virtual void Act() { }
    }
    

        功能

  • AddState:添加新状态到 FSM
  • DeleteState:从 FSM 中删除状态。
  • SetCurrentState:设置当前状态。
  • PerformTransition:执行状态转换。
  • public class FSMSystem
    {private List<FSMState> states;// 改变 FSM 状态的唯一方法是执行转换// 不要直接更改 CurrentStateprivate StateID currentStateID;public StateID CurrentStateID { get { return currentStateID; } }private FSMState currentState;public FSMState CurrentState { get { return currentState; } }public FSMSystem(){states = new List<FSMState>();}public void SetCurrentState(FSMState s){currentState = s;currentStateID = s.ID;s.DoBeforeEntering();}public void AddState(FSMState s, Ctrl ctrl){// 在删除之前检查空引用if (s == null){Debug.LogError("FSM 错误:不允许空引用");}s.FSM = this;s.CTRL = ctrl;// 插入的第一个状态也是初始状态,// 模拟开始时机器所处的状态if (states.Count == 0){states.Add(s);return;}// 如果状态不在列表中,则将其添加到列表中foreach (FSMState state in states){if (state.ID == s.ID){Debug.LogError("FSM 错误:无法添加状态 " + s.ID.ToString() +" 因为状态已经被添加");return;}}states.Add(s);}public void DeleteState(StateID id){// 在删除之前检查 NullStateif (id == StateID.NullStateID){Debug.LogError("FSM 错误:不允许使用 NullStateID 作为真实状态");return;}// 搜索列表并删除其中的状态foreach (FSMState state in states){if (state.ID == id){states.Remove(state);return;}}Debug.LogError("FSM 错误:无法删除状态 " + id.ToString() +"。它不在状态列表中");}public void PerformTransition(Transition trans){// 在更改当前状态之前检查 NullTransitionif (trans == Transition.NullTransition){Debug.LogError("FSM 错误:不允许使用 NullTransition 作为真实转换");return;}// 检查当前状态是否有传递的转换StateID id = currentState.GetOutputState(trans);if (id == StateID.NullStateID){Debug.LogError("FSM 错误:状态 " + currentStateID.ToString() + " 没有目标状态 " +" 对于转换 " + trans.ToString());return;}// 更新 currentStateID 和 currentStatecurrentStateID = id;foreach (FSMState state in states){if (state.ID == currentStateID){// 在设置新状态之前进行状态的后处理currentState.DoBeforeLeaving();currentState = state;// 在状态可以推理或行动之前重置其到所需条件currentState.DoBeforeEntering();break;}}} // PerformTransition()} //class FSMSystem
    

 

 

 


http://www.ppmy.cn/server/114850.html

相关文章

DeepSeek API是什么

DeepSeek API 是一个提供人工智能服务的接口&#xff0c;它允许开发者通过简单的API调用来实现各种高级的自然语言处理&#xff08;NLP&#xff09;任务&#xff0c;如文本生成、对话系统、文本摘要、问答系统等。DeepSeek API 通常基于先进的大模型&#xff0c;如Transformer架…

第L8周:机器学习|K-means聚类算法

本文为&#x1f517;365天深度学习训练营中的学习记录博客 &#x1f356; 原作者&#xff1a;K同学啊 | 接辅导、项目定制 &#x1f680; 文章来源&#xff1a;K同学的学习圈子深度学习 聚类算法的定义&#xff1a; 聚类就是将一个庞杂数据集中具有相似特征的数据自动归类到一…

ZooKeeper 中的 Curator 框架解析

Apache ZooKeeper 是一个为分布式应用提供一致性服务的软件。它提供了诸如配置管理、分布式同步、组服务等功能。在使用 ZooKeeper 时&#xff0c;Curator 是一个非常流行的客户端库&#xff0c;它简化了 ZooKeeper 的使用&#xff0c;提供了高级的抽象和丰富的工具。本文将详细…

MyBatis中Collection和Association的底层实现原理

MyBatis中Collection和Association的底层实现原理 Hi &#x1f44b;, Im shy 有人见尘埃&#xff0c;有人见星辰 技术咨询 引言 在 MyBatis 中&#xff0c;<collection> 和 <association> 标签用于处理一对多和一对一的关系。这两个标签在底层通过缓存、对象创…

Filebeat中间件监控指标解读

监控易是一款强大的系统监控工具&#xff0c;它能够全面监控IT系统的运行状态&#xff0c;及时发现问题并预警&#xff0c;确保系统的稳定性和高效运行。在本次解读中&#xff0c;我们将重点关注Filebeat中间件的监控指标。 Filebeat是一个轻量级的日志采集器&#xff0c;用于收…

Newtonsoft.Json (Json.NET)使用笔记

Newtonsoft.Json 简单介绍许可证功能特点 代码示例基本类型的序列化和反序列化对象与集合的序列化和反序列化对象的序列化与反序列化集合的序列化和反序列化 自定义转换器的使用自定义日期格式自定义转换器处理特殊类型 动态类型和 LINQ to JSON使用动态类型解析未知结构的 JSO…

SprinBoot+Vue二手回收微信小程序的设计与实现

目录 1 项目介绍2 项目截图3 核心代码3.1 Controller3.2 Service3.3 Dao3.4 application.yml3.5 SpringbootApplication3.5 Vue3.6 uniapp代码 4 数据库表设计5 文档参考6 计算机毕设选题推荐7 源码获取 1 项目介绍 博主个人介绍&#xff1a;CSDN认证博客专家&#xff0c;CSDN平…

Python Pandas数据处理利器query方法解析

大家好&#xff0c;在数据分析中&#xff0c;数据过滤是常见且重要的操作。Pandas库提供了多种方法来筛选数据&#xff0c;其中 query 方法因其简洁和强大的表达能力受到广泛欢迎。本文将详细介绍Pandas query 方法的高级应用&#xff0c;助力大家在复杂数据过滤时更加得心应手…