一个unity有限状态机框架
概述
有限状态机又称有限状态自动机,简称状态机。
- 定义:有限的多个状态在不同条件下相互转换的流程控制系统。
- 状态:物体表现出来的状况,多指行为。比如奔跑,攻击这些都属于状态。
- 条件:状态改变的依据。比如按下攻击键,按下奔跑键。
- 状态转换表:配置角色状态和条件的一张表。
- 状态机:管理所有的状态,协调组织状态的迁移。
有限状态机的适用范围:敌人AI, 玩家托管,游戏/软件整体框架,可交互教程,所有的流程控制系统
框架构建思路:
首先我们构建一个状态表如下:
| 当前状态 | 条件 | 目标状态 |
|---|---|---|
| Idle | 按下移动键 | Run |
| 按下跳跃键 | Jump | |
| 按下技能键 | Attack | |
| 按下翻滚键 | Scroll | |
| HP为空 | Dead | |
| Run | 按下跳跃键 | Jump |
| 按下技能键 | Attack | |
| 按下翻滚键 | Scroll | |
| 什么都不做 | Idle | |
| HP为空 | Dead |
我们发现一个角色会有多个状态,一个状态会有多个转换条件对应的状态。我们发现状态和条件均为变化点,所以我们要将状态提成不同的类,条件提成不同的类来分离变化点。
每一个状态会有若干个个条件与状态的对应,这种对应我们可以使用字典结构来实现,此字典由状态机配置时调用。这样分析那么也就是说一个状态中会有多个转换用的条件,我们还需要一个条件数组来存储条件的实例对象。
我们还需要一个类来管理一个角色上所有的状态,我们将这个类命名为状态机。
但是这里就会存在几个问题。
- 条件的实例对象从哪里来?
状态机作为管理角色状态的类,可以创建一个方法在状态机初始化的时候为这个对象的所有状态赋值初始化包括条件对象。当然我们也可以使用反射来创建条件对象。当状态机为角色状态初始化并配置状态与条件的映射关系时,由状态动态创建条件对象并添加到条件数组。
- 如何实现自动切换状态?
状态机中需要使用帧更新来每帧检查当前状态的条件表是否有满足的条件,如果满足就切换。
代码&注释
本人叙述能力实在有限下面是代码实现,包含注释详解:
FSMTriggerID:条件ID枚举
namespace CharacterControlSystem.CharacterFSM
{
public enum FSMTriggerID
{
JumpToIdleDetection,
MoveToIdleDetection,
IdleToMoveDetection,
IdleToJumpDetection,
}
}
FSMStateID:状态ID枚举
namespace CharacterControlSystem.CharacterFSM
{
public enum FSMStateID
{
Default,
Idle,
Run,
Jump,
}
}
FSMTrigger:条件基类
using System;
using UnityEngine;
namespace CharacterControlSystem.CharacterFSM
{
/// <summary>
/// 有限状态机中的条件类基类
/// </summary>
public abstract class FSMTrigger
{
/// <summary>
/// 条件ID
/// </summary>
public FSMTriggerID TriggerId {
get; set; }
public FSMTrigger()
{
InitId();
}
/// <summary>
/// 子类必须实现此方法来为TriggerId赋值
/// 此方法由构造函数调用
/// </summary>
protected abstract void InitId();
/// <summary>
/// 子类必须实现此方法来处理条件逻辑,
/// 状态机通过检查所有状态的所有条件来判断需要切换至什么状态
/// 检测方法内部来判断此方法
/// </summary>
public abstract bool HandleTrigger(GameObject thisGameObject);
}
}
FSMState:状态基类
using System;
using System.Collections.Generic;
using UnityEngine;
namespace CharacterControlSystem.CharacterFSM

本文介绍了一个Unity有限状态机框架的设计与实现,详细解释了状态机的概念、构成元素及其在游戏开发中的应用。提供了状态机基类、状态基类及条件基类等核心组件的代码示例。
最低0.47元/天 解锁文章
866

被折叠的 条评论
为什么被折叠?



