news 2026/4/18 7:32:23

外部类触发角色状态切换

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
外部类触发角色状态切换

在使用状态机的时候,很容易出现这种情况

在游戏开发中,当其他类(比如敌人、道具、环境等)触发了某个事件,想要改变玩家的状态,而玩家使用的是状态机(State Machine)来管理行为和状态,那么关键在于:如何优雅地让外部事件通知状态机,进而触发玩家状态的变更或行为的调整

下面是几种常见且合理的实现方式,按照推荐程度和清晰度排序:


一、核心思路

状态机通常封装了玩家当前的状态以及状态之间的切换逻辑。外部不应该直接修改玩家的状态(比如强制将状态设为“跳跃”或“受伤”),而是应该通过事件/消息/接口通知玩家对象,由玩家内部的状态机决定如何响应。


二、推荐的实现方案

方案1:通过事件/消息系统通知玩家(解耦推荐 ✅✅✅)

适用场景:游戏架构较为复杂,希望各系统之间低耦合,比如使用观察者模式、事件总线(Event Bus)、信号槽(Signal/Slot)等。

实现步骤:
  1. 定义事件类型

    • 比如PlayerHitEventPowerUpCollectedEventEnemyNearbyEvent等。
  2. 其他类触发事件

    • 当敌人攻击玩家时,敌人不直接调用玩家的方法,而是向事件系统发送一个事件,如:

      csharp

      EventSystem.Publish(new PlayerHitEvent(damage));
  3. 玩家对象监听事件

    • 玩家类(或状态机类)注册监听这些事件,当收到事件后,通知当前状态或者直接让状态机处理
    • 例如:

      csharp

      // 在玩家初始化时 EventSystem.Subscribe<PlayerHitEvent>(OnPlayerHit); private void OnPlayerHit(PlayerHitEvent e) { stateMachine.HandleEvent(e); // 或直接调用状态机方法 }
  4. 状态机或具体状态处理事件

    • 状态机有一个统一的事件处理入口,或者每个状态自己处理关心的事件。
    • 例如,在状态机中:

      csharp

      public void HandleEvent(GameEvent e) { currentState.HandleEvent(e); }
    • 每个状态类实现自己的HandleEvent方法,决定是否要切换状态或执行某些行为。

优点:高度解耦,易于扩展和维护,适合大型项目。
缺点:需要实现事件系统,稍微复杂一点。


方案2:通过玩家暴露的接口方法(直接但需控制访问 ✅✅)

适用场景:中小型项目,事件系统未引入,但依然希望有一定封装性。

实现步骤:
  1. 在玩家类中提供“受保护”的方法或通过状态机暴露接口

    • 比如:

      csharp

      public class Player { public StateMachine StateMachine { get; private set; } // 外部不直接调用 SetState,而是调用统一接口 public void TakeDamage(int damage) { stateMachine.HandleDamage(damage); } public void CollectPowerUp(PowerUpType type) { stateMachine.HandlePowerUp(type); } }
  2. 状态机或当前状态处理逻辑

    • 状态机根据不同输入,决定是否切换状态。例如:

      csharp

      public void HandleDamage(int damage) { if (currentState is NormalState) { // 切换到受伤状态或减少血量后可能进入击倒状态 ChangeState(new HurtState()); } }

优点:比直接操作状态更安全,逻辑集中。
缺点:如果接口设计不好,仍可能导致外部误用。


方案3:直接调用状态机/设置状态(不推荐 ❌❌❌,除非非常简单)

即:其他类直接调用类似player.StateMachine.ChangeState(new HurtState())player.SetState("Hurt")

⚠️为什么不推荐?

  • 破坏封装性:状态机是玩家内部行为管理机制,外部直接控制状态,容易导致逻辑混乱。
  • 难以维护和调试:多个系统随意切换玩家状态,难以追踪状态流转。
  • 不符合面向对象设计原则:高耦合,低内聚。

🔒除非是极其简单的原型阶段,否则应避免这种做法。


三、最佳实践建议总结

方法耦合度可维护性推荐度适用阶段
事件/消息系统(观察者/Event Bus)✅✅✅中大型项目,复杂交互
玩家封装接口,由状态机处理中高✅✅中小型项目,结构清晰
直接操作状态机/状态❌❌❌原型阶段,临时调试用

四、举个例子(伪代码/简化版)

假设:

  • 玩家有状态机,当前可能是 Idle、Run、Hurt、KnockDown 等状态。
  • 敌人攻击玩家,希望让玩家受伤。

事件驱动方式(推荐)👇

csharp

// 敌人攻击时 void AttackPlayer() { int damage = 10; EventSystem.Publish(new PlayerHitEvent(damage, this)); } // 玩家初始化时订阅事件 void Start() { EventSystem.Subscribe<PlayerHitEvent>(OnHit); } void OnHit(PlayerHitEvent e) { stateMachine.HandleDamage(e.Damage); } // 状态机或状态内部处理 public void HandleDamage(int damage) { if (CurrentState is NormalState) { ChangeState(new HurtState()); health -= damage; } }

五、补充:状态机设计建议

  • 状态模式(State Pattern)是实现状态机的经典方式,每个状态是一个类,实现统一的接口,比如IState,包含Enter()Update()Exit()HandleEvent()等方法。
  • 上下文(Context)是玩家自己,它持有当前状态对象,并委托行为给状态。
  • 通过这种方式,状态的切换和行为都封装在状态类中,外部只关心“发生了什么”,而不关心“怎么切换”。

总结一句话:

🎮当其他类需要影响玩家状态时,不要直接操作玩家状态机,而应该通过事件通知、接口调用等间接方式,最终由玩家的状态机根据逻辑决定是否以及如何切换状态。推荐使用事件系统实现解耦,保障代码清晰可维护。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/25 14:34:35

YOLOv12官版镜像导出ONNX,跨平台部署无忧

YOLOv12官版镜像导出ONNX&#xff0c;跨平台部署无忧 YOLO系列模型早已成为工业界目标检测的“事实标准”——从智能工厂的缺陷识别、物流分拣系统的包裹定位&#xff0c;到城市交通摄像头中的车辆追踪&#xff0c;它的身影无处不在。但每次升级换代&#xff0c;开发者总要面对…

作者头像 李华
网站建设 2026/4/18 7:22:55

如何实现静音剔除?FSMN-VAD语音预处理实战教程

如何实现静音剔除&#xff1f;FSMN-VAD语音预处理实战教程 1. 为什么静音剔除是语音处理的第一道关卡&#xff1f; 你有没有遇到过这样的问题&#xff1a;一段10分钟的会议录音&#xff0c;真正说话的时间可能只有3分半&#xff0c;其余全是咳嗽、翻纸、键盘敲击和长时间停顿…

作者头像 李华
网站建设 2026/4/16 14:41:10

Qwen3-Embedding-4B与Llama3嵌入模型对比:推理速度实测

Qwen3-Embedding-4B与Llama3嵌入模型对比&#xff1a;推理速度实测 1. Qwen3-Embedding-4B介绍 Qwen3 Embedding 模型系列是 Qwen 家族中专为文本嵌入和排序任务打造的最新成员&#xff0c;基于强大的 Qwen3 系列密集基础模型构建。该系列覆盖了从 0.6B 到 8B 不同参数规模的…

作者头像 李华
网站建设 2026/4/16 19:55:12

MinerU提取公式出错?模糊图像增强处理实战方案

MinerU提取公式出错&#xff1f;模糊图像增强处理实战方案 1. 问题背景&#xff1a;PDF复杂内容提取的现实挑战 你有没有遇到过这种情况&#xff1a;好不容易找到一份关键的技术文档或学术论文&#xff0c;结果用常规工具一转Markdown&#xff0c;公式乱码、表格错位、图片丢…

作者头像 李华
网站建设 2026/4/17 15:14:28

checkpoint如何选择?Qwen2.5-7B最佳模型判断

checkpoint如何选择&#xff1f;Qwen2.5-7B最佳模型判断 在实际微调Qwen2.5-7B的过程中&#xff0c;一个常被忽视却至关重要的环节是&#xff1a;训练结束后&#xff0c;面对多个checkpoint文件&#xff0c;到底该选哪一个&#xff1f; 不是最新生成的就最好&#xff0c;也不是…

作者头像 李华
网站建设 2026/4/12 9:46:22

PyTorch-2.x镜像使用心得:开发者日常开发提效实践

PyTorch-2.x镜像使用心得&#xff1a;开发者日常开发提效实践 作为一名长期在深度学习一线“搬砖”的开发者&#xff0c;我深知一个干净、高效、开箱即用的开发环境对生产力的提升有多关键。过去每次换机器或协作项目时&#xff0c;光是配置 Python 环境、装 CUDA 驱动、解决包…

作者头像 李华