Unity FSM的原理及实现

按照规矩上代码前先来一键三连,搞错了重来,先来一键三问。

1.什么是FSM

2.FSM能干什么?

3.为什么要用FSM

对于上面三个问题,我们一一解答

1.FSM全称是Finite State Machine,中文名是有限状态机,为什么叫有限状态机? 有限指的是状态的个数是有限的。

2.FSM是管理一组能相互切换状态的机器。

3.举个例子:我们有如下状态和条件

1.1

我们发现当前处于某个状态下的条件一旦满足,就会切换到另一个状态,也就是条件驱动状态的切换。当状态和条件复杂的时候就需要FSM对这些东西进行管理。

解决了一键三问,我们来看看FSM到底要怎么实现。

还是使用图1.1的例子我们先分析一下,状态对应不同的判断条件,而且以后肯定会增加新条件或者改变条件,如果条件写在对应状态里面,那条件发生改变的时候状态类也要去改动,根据面向对象的模式这违反了开闭原则,我们需要把条件写成类,这样增加条件或者修改条件我们只需要对条件类进行处理。

我们现在知道条件应该做成一个类,那么条件类具体应该干什么呢?

图1.1条件类就是处理条件判断的逻辑,查看自己是否满足了,满足就要切换到下一个状态。

拿 检测到移动输入/跳跃输入 举例我们来写一些伪代码

class InputMovingCondition{            class InputJumpingCondition{

    public bool IsInputMoving() {            public bool IsInputJumping() {

        if(正在移动输入)                                 if(正在跳跃输入){
            return true                                            return true

        else                                                    else

            return false                                            return false

    }                                                        }

}                                                    }

说完条件类,我们来看下状态类,状态类到底应该干什么呢?

图1.1,我们发现状态类里面要应该要存放多个条件满足->切换状态的对应关系,然后需要遍历所有条件,看一下哪个条件满足了,满足之后就要去通知状态机切换到对应的状态。而且每个状态要执行的逻辑也各不相同,移动跳跃或是攻击等等。

最后状态机到底干什么呢?

图1.1并没有标出状态机,状态机在后台把控全局类似军师的角色,当前是什么状态,状态怎么切换这些都是状态机去负责的。

根据上面的分析,我们先写以下的代码

条件基类:

条件基类

状态基类:

状态基类

状态机基类:

状态机基类

基本的框架已经搭好了,里面还有些地方我们需要改动,我们接着往下走

先看状态基类,mapping这个参数还没有设置,对应关系应该是状态机为状态设置的,状态基类中处理状态的地方不够详细,我们可能需要状态进入和状态退出的事件,这也需要状态机去提供,分析了这些之后再去进行修改

条件基类:

public abstract class FSMCondition

    {

        //我只知道我要条件判断,具体判断什么要让子类重写

        public abstract bool HandleCondition(FSMBase fsmBase);

    }

状态基类:

public abstract class FSMState

    {

        //条件->状态的对应关系

        private Dictionary<FSMCondition,FSMState> mapping;

        //由状态机为我们配置映射关系

        public void ConfigMapping(FSMCondition condition, FSMState state)

        {

            mapping.Add(condition,state);

        }

        //这方法让状态机每帧去调用判断

        public void CheckCondition(FSMBase fsmBase)

        {

            //便利自身所有的条件

            foreach(FSMCondition condition in mapping.Keys)

            {

                if(condition.HandleCondition(fsmBase))

                {

                    //告诉状态机切换到对应状态,那参数需要FSMBase

                    fsmBase.SwitchState(mapping[condition]);

                    return;

                }

            }

        }

        //状态中自己要干的事,具体做什么还是要子类去重写

        public abstract void OnStateEnter(FSMBase fsmBase);

        public abstract void OnStateStay(FSMBase fsmBase);

        public abstract void OnStateExit(FSMBase fsmBase);

    }

状态机基类:

public abstract class FSMBase : MonoBehaviour

    {

        //当前在哪个状态

        protected FSMState currentState;

        //添加状态,并为每个状态去设置应对关系

        protected abstract void AddStateAndConfigMapping();

        //切换状态,切到哪个状态?由状态类调用

        public void SwitchState(FSMState fsmState)

        {

            currentState.OnStateExit(this);//退出旧状态

            currentState = fsmState;

            currentState.OnStateEnter(this);//进入新状态

        }

        protected void Start()

        {

            AddStateAndConfigMapping();

        }

        protected void Update()

        {

            //调用状态类里面的条件判断

            currentState.CheckCondition(this);

            currentState.OnStateStay(this);//正在状态中

        }

    }

FSM写完后,我们用图1.1案列去使用一下

状态机类:

用户控制的状态机

状态类:

闲置状态类
移动状态类
跳跃状态类

条件类:

检测跳跃输入
检测跳跃结束
检测移动输入
检测停止移动输入

FSM的简单实现就完成了

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 221,198评论 6 514
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,334评论 3 398
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 167,643评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,495评论 1 296
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,502评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,156评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,743评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,659评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,200评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,282评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,424评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,107评论 5 349
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,789评论 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,264评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,390评论 1 271
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,798评论 3 376
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,435评论 2 359

推荐阅读更多精彩内容