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

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

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

  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 frame
    void Update()
    {
//更新状态的方法
        stm.UpdateState();
    }
}

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

 

posted @ 2018-10-12 23:19  低调的风仔  阅读(4985)  评论(0编辑  收藏  举报