Unity有限状态机详解

这阵子用到了有限状态机,于是花了一段时间研究了一下。在这里我会详细的讲解有限状态机的原理以及如何编写一个有限状态机。

有限状态机算是Unity开发中一个比较重要的技巧了。那什么什么是有限状态机呢?在游戏中,我们可能会遇到各种各样的状态,这里我以一个人人物为例,我们可能要经常判断人物的生命状态或者人物的运动状态,然后做相应的操作。

这里写图片描述

我们可以用Switch语句来获取状态,并且通过特定的方法来设置状态。但我们可能要在项目的很多地方的调用这段Switch方法,或者设置当前人物的状态。当状态比较多的时候,对状态的管理和获取也会变得更加麻烦。

Switch(人物生命状态)
{
    Case Alive:
        do something();
    Case Alive:
        do something();
    break;
}

Switch(人物运动状态)
{
    Case Run:
        do something();
    Case Idle:
        do something();
    Case Walk:
        do something();
    break;
}

所以这个时候,我们需要一个有限状态机(Finite State Machine)来集中的管理状态(State)。现在我们来看看如何设计一个有限状态机。

有限状态机包含两个部分①状态集(FSMState),②状态管理机(FSMSystem),我们先从状态集开始设计。

①状态集(FSMState)的设计

状态基代表一组状态的集合,比如上面的人物,他的状态集是这样的

enum PersonLifeState
{
        died,
        alive 
}

enum PersonSportState
{
        run,
        idle,
        walk    
}

一个游戏当中可能需要多个状态集,所以我们在设计FSMState,最好将他设计为抽象类,这样就能通过继承FSMState,拥有一些公共的属性和方法,同时又有自己特定的状态。我设计的方式如下,通过一个List,可以让FSMState的派生类添加属于自己特有的状态,同时有一个变量保存当前的State。

public abstract class FSMState
{
    private List<State> list= new List<State>();
    private State curState;

    /*添加状态集中的状态*/
    public void AddState(State state)
    {
        if (list.Contains(state))
       {
            return;
        }
        list.Add(state);
    }

    /*设置当前的状态,注意这里为私有方法,这样可以让派生类无法直接设置状态,而是让状态机来统一设置*/
    private bool setCurState(State state){
        if(list.Contains(state)){
            curState=state;
            return true;
        }else{
            return false;
        }
    }

    ……
    //可以自己根据业务,设计一些共有的抽象方法
}

现在有了状态集了,我们还需要设计状态(State)。一个游戏中有各种各样的状态,我们要怎么设计呢?我们可以把特定集合的状态放在不同的枚举里,不过,我设计的是将所有状态放在一个枚举类里面。代码如下。

public enum State
{
    died, 
    alive,

    walk,
    run,
    stop 
}`

这样,我们就可以继承这个FSMState基类,然后添加特定的状态了。

人物生命状态

public class PersonLifeState :FSMState
{
    ……
}

/*PersonLifeState 添加自己特有的状态*/
PersonLifeState personLife= new PersonLifeState ();
personLife.AddState(State.died);
personLife.AddState(State.alive);

人物运动状态

public class PersonSportState :FSMState
{
    ……
}

/*personSport 添加自己特有的状态*/
PersonSportState personSport = new PersonSportState ();
personSport .AddState(State.walk);
personSport .AddState(State.run);
personSport .AddState(State.stop );

现在,FSMState就设计好了,我们在来看看如何设计一个FSMSystem

①状态管理机(FSMSystem)的设计

一个状态管理机主要的功能有这两点

  • 能够添加和删除状态集(FSMState)
  • 能够切换和获取某个状态集(FSMState)当前的状态(State)

知道了FSMSystem最主要的功能,我们现在就可以来自己设计一个了。我设计的FSMState代码如下

public class FSMSystem
{

    /*通过一个List专门用来存储FSMState */
    private List<FSMState> statesList=new List<>();

    /*添加FSMState的方法 */
    public void AddState(FSMState states)
    {
        /*做空判断检测*/
        if (statesList== null)
        {
            Debug.LogError("FSM ERROR");
        }

        /*当states为空时直接添加*/
        if (stateList.Count == 0)
        {
            statesList.Add(states);
            return;
        }

        /*当states不为空时,检查是否重复*/
        if(!statesList.contans(states)){
            states.Add(s);
        }

    }

    /*删除状态集合*/
     public void DeleteState(FSMState states)
    {
        if(!statesList.contans(states))
        {
            states.Remove(states);
        }
    }

    /*获取某个状态集的当前状态*/
    public State GetCurState(FSMState states)
    {   
        if(!statesList.contans(states))
        {
            states.getCurState();
        }
    }

    /*改变某个状态集的当前状态*/
    public void ChangeState(FSMState states,State state)
    {
        if(!statesList.contans(states))
        {
            states.setCurState();
        }
    }

}

这样我们就把状态机FSMSystem设计好了,我们将FSMState的派生类强行转换成FSMState基类,就能让FSMSystem统一进行管理了。上面的代码只是我设计有限状态机的一种思路,用来参考就行了。只要掌握了有限状态机的原理,你可以自己设计符合业务逻辑的状态机。虽然有限状态机比switch的方法要复杂很多,但是却能大大的简化代码逻辑。学会并使用有限状态机还是蛮重要的。

猜你喜欢

转载自blog.csdn.net/tyuiof/article/details/53037363
今日推荐