设计模式之状态模式(State)

发表于2018-11-04
评论6 6.8k浏览

状态模式主要用于状态机的设计,更加便利的控制切换对象状态,增强可扩展性和可维护性。状态机不仅适用于角色动作状态,同样适用于其他可以确切划分为相互独立的区间的功能模块。

一、 有限状态机:
又称FSM有限状态机,集合了对象所有的状态,通过外界输入和内部逻辑切换状态,保证同一时间只有一个状态,各状态相互独立,每个状态包含了切入、刷新、切出三部分,配合Unity的Animator使用效果更佳~~
    //状态基类
    public abstract class FSMState
    {
        public abstract void OnEnter();
        public abstract void Update();
        public abstract void OnExit();
    }
    //控制器
    public class FSMController
    {
        public FSMState curState { get; protected set; }
        public void ChangerState(FSMState state)
        {
            if (state != null)
            {
                if (curState != state)
                    curState.OnExit();
                curState = state;
                curState.OnEnter();
            }
        }
        public void Update()
        {
            curState.Update();
        }
    } 
二、 并发状态机:
有限状态机只能保持单一状态,比如玩家有行走、跑动、跳跃、下蹲、攻击等状态,攻击又分为远程射击、投掷手雷、近身挥砍等,FSM不能同时移动并攻击。
这时候就需要两个独立的有限状态机,分别控制攻击状态和移动等其他状态,接收输入指令执行相应状态。(还可以设置让状态机销毁输入,对应的状态机接收输入指令后销毁输入,避免两个状态机重复响应。)有时候两个状态机需要交互,加入在跳跃的时候不能投掷手雷,这还需要在响应输入的时候对另一个状态进行判断。

三、分层状态机:
状态可以继承自父状态,收到输入指令进行判断,若不在判断范围,再交给父状态类判断处理。
public enum HeroState
{
    stand,
    walk,
    run,
}
public class OnGroundState
{
    public virtual void HandleInput(HeroState toState)
    {
        if(toState == HeroState.stand)
        {
        }
        else if (toState == HeroState.walk)
        {
        }
        else if(toState == HeroState.run)
        {
        }
        //······
    }
}
public class StandState : OnGroundState
{
    public override void HandleInput(HeroState toState)
    {
        if (toState == HeroState.stand)
        {
        }
        else if (toState == HeroState.walk)
        {
        }
        //······
        //不在处理范围,返回给父类
        base.HandleInput(toState);
    }
} 
四、下推状态机:
举个栗子:玩家切换到射击状态,发射子弹,播放动画、特效、音效等等,在执行完射击动作后,需要再切换回到之前的状态,但之前状态可能是站立,也可能是行走、奔跑、跳跃···,在有限状态机中,使用一个状态指针来记录当前状态,那么下推状态机则是用一个状态指针队列来顺序记录状态。
比如用队列Queue来记录,新加入的状态会在最上面,状态执行完成,自动切换时弹出最上面的值,下一个值将成为新的状态。在前面的栗子中,射击结束后,就可以很容易的获取到之前的状态了。

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引

标签: