在Unity中实现有限状态机
概要
本文将介绍Unity开发中的有限状态机,给出对应的实现代码。
背景
有限状态机借鉴了图灵机的思想,可以看作是最简单的图灵机。
它包含4要素:
- 现态
- 条件
- 动作
- 次态
有限状态机的基本实现
基础的有限状态机不复杂,无非是几个状态定义成类,提供OnEnter/OnExit/OnUpdate方法,这里直接根据需求给出对应的代码实现。
需求
- 按住左Ctrl蓄力
- 蓄力0.5s 内松开取消蓄力
- 蓄力2.0s 内松开播放技能动作1
- 蓄力2.0s 以上松开播放技能动作2
- 蓄力超过3.5s 播放技能动作2
- 点击空格跳跃
实现
抽象类,定义进入状态和退出状态的行为
public interface IState
{
public IState OnUpdate(Character t);
public void OnEnter(Character t);
public void OnExit(Character t);
}
状态机的关键在于控制状态的切换,这里直接在Character里进行相关逻辑控制。
public class Character : MonoBehaviour
{
public Animator animator;
protected IState state;
public virtual void Update()
{
if (null != state)
{
IState newState = state.OnUpdate(this);
//状态切换
//state switch
if (null != newState)
{
TransitionState(newState);
}
}
}
/// <summary>
/// 状态切换
/// Transition state
/// </summary>
/// <param name="newState"></param>
public void TransitionState(IState newState)
{
Debug.Log($"状态变更{newState}");
newState.OnEnter(this);
if (null != state)
state.OnExit(this);
state = newState;
}
}
演示一个技能类
public class UltimateSkillState : IState
{
private int _fullPathHash;
private int _skillId;
private float _dt = 0;
private int _prevHashId = 0;
public void OnEnter(Character t)
{
_dt = 0;
t.animator.SetInteger(AnimationTriggers.hashIdDefaultSkill, _skillId);
}
/// <summary>
/// 构造
/// </summary>
/// <param name="skillId">技能id</param>
/// <param name="animatorFullPath">动画全路径(如Base Layer.Jump)</param>
public UltimateSkillState