当前位置: 首页 > article >正文

Unity状态机的实现方法一

Unity状态机知识点整理

1. 状态机基本概念

1.1 什么是状态机

Unity常见的状态机管理分为三种:

  1. 枚举状态机
  2. 通过实现接口的方式多态出的更加便于维护的状态机
  3. Unity Animator自带的StateMachineBehaviour

1.2 不同状态机实现方式的对比

自定义状态机(枚举/接口)特点:
  1. 控制灵活度

    • 完全自主控制状态转换逻辑
    • 可以方便地访问和修改游戏对象的任何组件
    • 能够实现复杂的状态嵌套和组合
  2. 性能优势

    • 代码执行效率高
    • 内存占用小
    • 可以精确控制状态检查的频率
  3. 调试便利性

    • 可以方便地添加调试信息
    • 状态切换逻辑清晰可见
    • 便于断点调试
  4. 使用场景

    • 适合复杂的游戏逻辑控制
    • 需要频繁状态切换的情况
    • 需要与其他系统紧密集成的情况
StateMachineBehaviour特点:
  1. 可视化优势

    • 在Animator窗口中可视化编辑
    • 状态转换条件直观显示
    • 便于美术和策划理解和配置
  2. 动画集成

    • 与动画系统紧密结合
    • 自动处理动画过渡
    • 内置动画事件支持
  3. 局限性

    • 状态逻辑需要通过特定的回调函数实现
    • 访问其他组件相对繁琐
    • 不适合处理复杂的游戏逻辑
  4. 使用场景

    • 主要用于动画状态控制
    • 简单的行为状态切换
    • 需要可视化编辑的情况

1.3 StateMachineBehaviour示例

public class PlayerRunBehavior : StateMachineBehaviour
{
    // 状态进入时调用
    override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    {
        // 初始化逻辑
    }

    // 状态更新时调用
    override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    {
        // 更新逻辑
    }

    // 状态退出时调用
    override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    {
        // 清理逻辑
    }
}

1.4 选择建议

  1. 使用自定义状态机当:

    • 需要处理复杂的游戏逻辑
    • 需要高性能和精确控制
    • 状态之间有复杂的数据传递
    • 需要与多个系统交互
  2. 使用StateMachineBehaviour当:

    • 主要处理动画相关的状态
    • 需要可视化编辑状态流程
    • 团队中有非程序人员需要配置状态
    • 状态逻辑相对简单

2. 脚本中的状态机实现分析

2.1 状态定义

protected enum State
{
    Normal,  // 普通状态
    Attack   // 攻击状态
}
protected State currentState;  // 当前状态

2.2 状态初始化

protected virtual void Awake()
{
    controller = GetComponent<CharacterController>();
    animator = GetComponent<Animator>();
    currentState = State.Normal;  // 初始化为普通状态
}

2.3 状态切换机制

protected void ChangeState(State state)
{
    // 退出当前状态
    switch(currentState)
    {
        case State.Normal:
            break;
        case State.Attack:
            break;
    }
    
    // 进入新状态
    switch(state)
    {
        case State.Normal:
            break;
        case State.Attack:
            animator.SetTrigger("Attack");  // 触发攻击动画
            break;
    }
    currentState = state;  // 更新当前状态
}

3. 枚举状态机的优势

3.1 代码组织优势

  • 结构清晰:每个状态的行为被清晰地划分
  • 易于维护:添加新状态只需扩展枚举和相应的处理逻辑
  • 代码复用:状态逻辑可以被多个角色类继承和复用

3.2 游戏逻辑优势

  • 状态隔离:不同状态的行为互不干扰
  • 转换控制:可以严格控制状态间的转换条件
  • 动画整合:便于与动画系统集成(如示例中的animator)

4. 使用流程

  1. 定义状态

    • 使用enum定义可能的状态
    • 声明当前状态变量
  2. 初始化

    • 在Awake或Start中设置初始状态
    • 获取必要的组件引用
  3. 状态切换

    • 实现状态切换方法
    • 处理退出当前状态的逻辑
    • 处理进入新状态的逻辑
    • 更新状态标记
  4. 状态更新

    • 在Update等生命周期方法中根据当前状态执行相应逻辑
    • 通过HandleMovement等抽象方法实现具体行为

5. 扩展建议

5.1 状态扩展示例

protected enum State
{
    Normal,
    Attack,
    Jump,    // 可添加跳跃状态
    Hurt     // 可添加受伤状态
}

5.2 功能扩展方向

  1. 状态参数

    • 可以为每个状态添加参数配置
    • 使用ScriptableObject存储状态配置
  2. 状态持续时间

    • 可以添加状态持续时间控制
    • 实现状态自动切换机制
  3. 状态嵌套

    • 可以实现状态的层级结构
    • 支持子状态机的实现

6. 注意事项

  1. 状态切换的原子性

    • 确保状态切换过程是完整的
    • 避免状态切换过程中的中断
  2. 性能考虑

    • 避免频繁的状态切换
    • 合理控制状态数量
  3. 代码维护

    • 保持状态逻辑的独立性
    • 做好状态切换的条件管理
    • 适当的注释和文档说明

以上是Unity两种状态机的实现方式,更便于维护的状态机是枚举状态机,此内容会在后续的投稿中更新!!!!!


http://www.kler.cn/a/545504.html

相关文章:

  • 【Elasticsearch】字符过滤器Character Filters
  • 深度学习|表示学习|归一化和正则化带给我们的启示|27
  • 前端开发:打造磨砂质感的盒子效果
  • python自动化测试之统一请求封装及通过文件实现接口关联
  • 使用 Flask 构建流式返回服务
  • Logistic Regression 逻辑回归中的sigmoid函数是什么?
  • 【Linux】多线程 -> 从线程概念到线程控制
  • 【CXX】0 Rust与C ++的互操作利器:CXX库介绍与示例
  • 深入解析:如何在C#和C/C++之间安全高效地通过P/Invoke传递多维数组
  • RV1126解码(1)
  • 多能互补综合能源系统,改变能源结构---安科瑞 吴雅芳
  • 探索ChatGPT背后的前端黑科技
  • 【每日关注】科技圈重要动态
  • JVM——垃圾回收器
  • Redis企业开发实战(五)——点评项目之分布式锁Redission与秒杀优化
  • 基于Spring Boot的网上宠物店系统设计与实现(LW+源码+讲解)
  • 【数据结构课设--内部排序算法的性能分析系统】
  • 考研操作系统----操作系统的概念定义功能和目标(仅仅作为王道哔站课程讲义作用)
  • 独立C++ asio库实现的UDP Server
  • 用python写一个聊天室程序