设计模式之状态模式(State)
发表于2018-11-04
状态模式主要用于状态机的设计,更加便利的控制切换对象状态,增强可扩展性和可维护性。状态机不仅适用于角色动作状态,同样适用于其他可以确切划分为相互独立的区间的功能模块。
一、 有限状态机:
又称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来记录,新加入的状态会在最上面,状态执行完成,自动切换时弹出最上面的值,下一个值将成为新的状态。在前面的栗子中,射击结束后,就可以很容易的获取到之前的状态了。