【转】有限状态机(FSM)学习总结C#

  FSM(Finite State Machine有限状态机)可以理解成是对行为逻辑的抽象,就好象人在生活中会做出各种行为,例如吃饭、睡觉等,这些所有我们都看作是“行为”的分支,由大脑决定每种行为具体是什么实施。在整个FSM架构中,其实与上面解释一致,首先有一个状态基类stateObject,里面有三个方法,分别是状态前、状态中、状态后。所有具体行为都要继承这个基类,在这三个方法中具体实现各种方法的逻辑。然后,需要一个stateManager(大脑)状态管理类来管理这些状态,特别注意的是里面changeState方法,他是状态跳转的关键。至于如果存储各种状态,你可以用list类 ,字典类等等。有限状态机就是把一个对象的行为分解成为易于处理的“块”或“状态”。

   例如将人的行为抽象成3个,分别是吃饭、睡觉、上班。上班族,只有吃饭、睡觉、上班三种行为,我们把这三种行为放进我们的大脑,即stateManager。那我们从什么行为开始呢?(其实这里就是initState),随便挑一个,默认为睡觉。之前说过,每个行为都有三个状态(前、中、后),当我们进入睡觉行为时,首先进入的是睡觉前状态(该状态只执行一次),然后进入睡觉中,真正的逻辑是在这里执行的,它会不停检查什么时候睡醒了,符合条件后跳到其他状态,当要进行跳转时,还会执行一次睡觉后状态,其实前、后状态我理解成当要执行或结束某种行为时,你要额外做的事情。例如,睡觉前我要带个眼罩。(放到游戏开发里可以进行一些赋值操作,或者调用其他类的方法,例如一些特效)。因为它编程快速简单,易于调试,性能高,与人类思维相似从而具有:1.便于梳理状态关系,2.使用灵活,3.容易修改

  FSM的优点就是因为它编程快速,简单,易于调试,性能高,与人类思维相似。

以下是一个自己写的实例代码,可供大家参考

首先创建一个抽象状态基类,里面有3个抽象方法,分别是进入状态,离开状态,更新状态的方法

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public abstract class StateObject
{//状态控制机protected StateManger sm;//构造函数public StateObject(StateManger _sm){sm = _sm;}//进入状态方法public abstract void EnterState();//离开状态方法public abstract void ExitState();//更新状态方法public abstract void UpdateState();}

 

然后根据具体的情况创建具体的状态类(继承自状态基类),我这里实现了3个具体的状态类,分别是人物默认状态,移动状态,死亡状态

默认状态方法

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class IdleState : StateObject
{public IdleState(StateManger _sm):base(_sm){}
//进入状态方法public override void EnterState(){Debug.Log("进入待定状态");}
//离开状态方法public override void ExitState(){Debug.Log("离开待定状态");}
//更新状态方法public override void UpdateState(){Debug.Log("更新待定状态");if (Input.GetKeyDown(KeyCode.M)){sm.ChangeState("Move");}else if (Input.GetKeyDown(KeyCode.D)){sm.ChangeState("Die");}}}

 

移动状态方法

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class MoveState : StateObject
{public MoveState(StateManger _sm) :base(_sm){}public override void EnterState(){Debug.Log("进入移动状态");}public override void ExitState(){Debug.Log("离开移动状态");}public override void UpdateState(){Debug.Log("更新移动状态");if (Input.GetKeyDown(KeyCode.D)){sm.ChangeState("Die");}else if(Input.GetKeyDown(KeyCode.I)){sm.ChangeState("Idle");}}
}

 

死亡状态方法

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class DieState : StateObject
{public DieState(StateManger _sm):base(_sm){}public override void EnterState(){Debug.Log("进入死亡状态");}public override void ExitState(){Debug.Log("离开死亡状态");}public override void UpdateState(){Debug.Log("更新死亡状态");if (Input.GetKeyDown(KeyCode.I)){sm.ChangeState("Idle");}}
}

 

然后,需要一个stateManager(大脑)状态管理类来管理这些状态,特别注意的是里面changeState方法,他是状态跳转的关键,需要放在Update函数中,因为需要不断检测当前的状态,检测是否跳转

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class StateManger {//利用字典存储各种状态Dictionary<string, StateObject> Dic = new Dictionary<string, StateObject>();//当前状态StateObject currentstate;//注册状态public void Region(string statename,StateObject state){if (!Dic.ContainsKey(statename)){Dic.Add(statename,state);}}//设置默认状态public void SetDefat(string statename){if (Dic.ContainsKey(statename)){currentstate = Dic[statename];currentstate.EnterState();}}//改变状态public void ChangeState(string statename){if (Dic.ContainsKey(statename)){if (currentstate!=null){currentstate.ExitState();currentstate = Dic[statename];currentstate.EnterState();}}}//更新状态public void UpdateState(){if (currentstate!=null){currentstate.UpdateState();}}}

 

这样一个简单的有限状态机就写好了,然后我们可以在Unity里面利用一个实例来测试一下,我写了一个控制物体状态的脚本

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class TestFsm : MonoBehaviour {//添加一个状态机StateManger stm = new StateManger();void Start(){//注册状态stm.Region("Idle", new IdleState(stm));stm.Region("Die", new DieState(stm));stm.Region("Move", new MoveState(stm));
//设置默认状态stm.SetDefat("Idle");}// Update is called once per framevoid Update(){
//更新状态的方法stm.UpdateState();}
}

复制代码

  以上就是本人学习FSM的一点总结,如果有什么不对的地方,敬请大家指出,大家一起学习进步。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/437096.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【转】[完全免费] 在线UML Sequence Diagram 时序图工具 - 教程第3部分

时序图教程 甲序列图描述了一组对象之间的相互作用参与协作&#xff08;或情况&#xff09;&#xff0c;布置成按时间顺序; 它通过它们的“生命线”和它们发送给对方的消息来显示参与交互的对象。 什么是UML中的序列图&#xff1f; UML序列图是详细说明如何执行操作的交互图。…

【转】[完全免费] 在线UML Class Diagram 类图工具 - 教程第1部分

在线Visual Paradigm - UML编辑器 使用在线UML编辑器轻松绘制UML图&#xff0c;其中包含功能强大的UML编辑工具&#xff0c;即时UML语法检查和整洁的用户界面。Visual Paradigm在线UML 图&#xff0c;如类&#xff0c;用例&#xff0c;序列&#xff0c;活动&#xff0c;部署&a…

python 定时器_python 线程之四:定时器(Timer),非阻塞

线程之一讲了线程&#xff0c;如果不熟悉&#xff0c;可以点击【线程之一&#xff1a;线程的创建、启动及运行方式】1、定时器实质&#xff1a;Timer 定时器源码实现&#xff0c;和我们自定义一个线程方式一样&#xff0c;都是继承了 Thread 类&#xff0c;重写了 run() 方法&a…

人如何认知事物?

自然界是连续的&#xff0c;人类将自然界离散化成一个个独立的概念&#xff0c;独立的概念相互关联&#xff0c;形成模型&#xff0c;随着模型的完善&#xff0c;模型会不断逼近真实事物。 比如人类创造了各种学科&#xff0c;就是从不同的方面深入研究世界的结果。 所以&…

域内定位个人PC的三种方式(1)

会话搜集 在cmd下调用query session命令可以获得当前环境下的windows会话 NetSessionEnum 这个函数不允许直接查询是谁登陆&#xff0c;但是它允许查询是谁在访问此工作站的网络资源时所创建的网络会话&#xff0c;从而知道来自何处&#xff0c;此函数不需要高权限即可查询 第…

02.Teams组成概述及使用分享

在上一篇博客中介绍了Teams的前世今生&#xff0c;大家对Teams已经有了一个初步的认识&#xff0c;但是如上一篇文章中所说Teams是一个集成度很高的云协作平台&#xff0c;具体应该怎么去有效的利用起来呢&#xff1f;接下来这篇博客给大家全方位的分享一下Teams的组成部分以及…

【Qt】解决GDAL直接读取数据到QImage导致图像歪斜的问题

QRect intersect_rect; .... QImage img(intersect_rect.size(), QImage::Format_RGB888); uchar *pImageData (unsigned char *)img.constBits(); int img_width intersect_rect.width(); int img_height intersect_rect.height();// QImage每行是按照sizeof(int)对齐的&am…

高斯课堂数电讲义笔记_【法考经验贴】40岁三战主观题127分!他的笔记学习法助他逆袭!...

这位学员在考证界算是“高龄学员”&#xff0c;高分过关依赖于他的努力和正确的学习方法&#xff1b;本文中他有重点介绍自己是如何做笔记的&#xff0c;非常值得大家学习借鉴&#xff01;一、个人概况&#xff1a;三战法考我正值不惑之年&#xff0c;是一名在职基层人民警察&a…

【转】持续交付和DevOps的前世今生

作者/分享人&#xff1a;乔梁&#xff0c;20年IT老兵&#xff0c;腾讯公司高级管理顾问&#xff0c;敏捷和精益开发专家&#xff0c;持续交付领域先行者。曾就职于百度&#xff0c;国内多个知名互联网公司的企业教练。 历年QCon技术大会的讲师和专题出品人。 这是一个新概念风起…

关联规则挖掘算法_基于Apriori关联规则的协同过滤算法

Apriori 算法apriori关联规则算法的原理设计较为简单&#xff0c;著名的“啤酒和尿布”说的就是Apriori算法&#xff0c;通俗来讲apriori旨在寻找频繁项集&#xff0c;以帮助商家将消费者有可能一起搭配购买的物品放置在同一个地方&#xff0c;提高消费者的购物效率和良好的购物…

【转】RabbitMQ六种队列模式-1.简单队列模式

前言 RabbitMQ六种队列模式-简单队列 [本文]RabbitMQ六种队列模式-工作队列RabbitMQ六种队列模式-发布订阅RabbitMQ六种队列模式-路由模式RabbitMQ六种队列模式-主题模式 在官网的教程中&#xff0c;描述了如上六类工作队列模式&#xff1a; 简单队列模式&#xff1a;最简单的…

【转】RabbitMQ六种队列模式-2.工作队列模式

前言 RabbitMQ六种队列模式-简单队列RabbitMQ六种队列模式-工作队列 [本文]RabbitMQ六种队列模式-发布订阅RabbitMQ六种队列模式-路由模式RabbitMQ六种队列模式-主题模式 上文我们了解了 RabbitMQ 六种队列模式中的简单队列&#xff0c;代码也是非常的简单&#xff0c;比较容易…

redis 哨兵模式 cluster模式区别_Redis哨兵(Sentinel)模式快速入门

当主服务器宕机后&#xff0c;需要手动把一台从服务器切换为主服务器&#xff0c;这就需要人工干预&#xff0c;费事费力&#xff0c;还会造成一段时间内服务不可用。 所以更多时候&#xff0c;我们优先考虑哨兵(sentinel) 模式。Redis sentinel是Redis高可用实现方案&#xff…

IOS开发入门笔记

IB&#xff1a;IB是指Interface Builder&#xff0c;如IBAction&#xff0c;IBOutlet。IBOutlet和IBAction是什么&#xff1f;IBOutlet&#xff1a;中文翻译应该是&#xff1a;插座&#xff0c;连接点&#xff08;书上写的是出口&#xff09;。autorelease相当于Qt中的deleteLa…

【转】RabbitMQ六种队列模式-3.发布订阅模式

前言 RabbitMQ六种队列模式-简单队列RabbitMQ六种队列模式-工作队列RabbitMQ六种队列模式-发布订阅 [本文]RabbitMQ六种队列模式-路由模式RabbitMQ六种队列模式-主题模式 上文的工作队列模式是直接在生产者与消费者里声明好一个队列&#xff0c;这种情况下消息只会对应同类型的…

组建一个局域网一般会用到哪些设备_路由器和交换机的区别是什么?在实际使用中有哪些不同...

电工之家&#xff1a;www.dgzj.com QQ群&#xff1a;2179090关注电工之家官方微信公众号“电工之家”&#xff0c;收获更多经验知识。其实关于路由器和交换机确实有很多人容易混淆&#xff0c;包括猫MOdem&#xff0c;我最初就认为猫就是路由器&#xff0c;现在回想起来真的傻…

【转】RabbitMQ六种队列模式-4.路由模式

前言 RabbitMQ六种队列模式-简单队列RabbitMQ六种队列模式-工作队列RabbitMQ六种队列模式-发布订阅RabbitMQ六种队列模式-路由模式 [本文]RabbitMQ六种队列模式-主题模式 本文带大家了解 RabbitMQ 队列模式中的路由模式。 其实只要看过上篇发布模式后&#xff0c;相信路由模式…

百度二年级手工机器人_让父母少弯腰的家务神器——追觅扫拖机器人慧目F9评测...

大家好&#xff0c;我是CC。父母都已过了花甲之年&#xff0c;退休在家本应是享清福的时候&#xff0c;为了照顾双上班族的我&#xff0c;平时承担了接儿子放学和给我蹭晚餐的任务&#xff0c;操劳不少。眼看着他们一点点老去&#xff0c;总想也为他们做点什么&#xff0c;所以…

【转】RabbitMQ六种队列模式-5.主题模式

前言 RabbitMQ六种队列模式-简单队列RabbitMQ六种队列模式-工作队列RabbitMQ六种队列模式-发布订阅RabbitMQ六种队列模式-路由模式RabbitMQ六种队列模式-主题模式 [本文] 从前面的几篇我们依次经历了 exchange 模式从 fanout > direct 的转变过程&#xff0c;在 fanout 时&a…