From 822dc90c2146ac8be5c9d0375c688f0df0f332eb Mon Sep 17 00:00:00 2001 From: Joywayer Date: Thu, 30 Jul 2026 16:23:47 +0800 Subject: [PATCH] =?UTF-8?q?refactor(enemy):=20=E6=B8=85=E8=A1=8C=E4=B8=BA?= =?UTF-8?q?=E6=A0=91=E5=80=BA=E2=80=94=E2=80=94StopBehaviorTree=20?= =?UTF-8?q?=E6=94=B9=E5=90=8D=EF=BC=8C=E5=88=A0=20ConsumeParryEvent?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit StopBehaviorTree → NotifyDecisionStop(方法体早已只是发 Died 信号)。 EnemyDeathSequence 的 _stopBehaviorTree 字段同步改名,带 FormerlySerializedAs 保值。 ConsumeParryEvent 及其 TTL 状态删除:零调用者,且 ForceState(Stagger) + IsControllable 让位门已是更优表达,不需要第二条受击通道。 顺带清掉这三个文件里残留的行为树插件措辞(BD_* / BD Task / 停行为树)。 Co-Authored-By: Claude Opus 5 (1M context) --- .../Enemies/Behaviors/EnemyDeathSequence.cs | 9 +-- .../Scripts/Enemies/Boss/ChaoFengBoss.cs | 6 +- Assets/_Game/Scripts/Enemies/EnemyBase.cs | 58 ++++++------------- 3 files changed, 26 insertions(+), 47 deletions(-) diff --git a/Assets/_Game/Scripts/Enemies/Behaviors/EnemyDeathSequence.cs b/Assets/_Game/Scripts/Enemies/Behaviors/EnemyDeathSequence.cs index ccc90118..cd9cbffe 100644 --- a/Assets/_Game/Scripts/Enemies/Behaviors/EnemyDeathSequence.cs +++ b/Assets/_Game/Scripts/Enemies/Behaviors/EnemyDeathSequence.cs @@ -9,7 +9,7 @@ namespace BaseGames.Enemies.Behaviors /// /// 死亡前摇无敌演出(零代码替代每敌人专属的 Die() 重写)。 /// - /// 会委托本组件:停行为树 / 停移动、停用受击框,播放前摇动画并等待, + /// 会委托本组件:通知决策层终止 / 停移动、停用受击框,播放前摇动画并等待, /// 期间敌人处于无敌(),演出结束后回调真正的死亡清理。 /// 前摇动画上可放置 SpawnProjectile 动画事件,配合 在演出中生成小怪。 /// @@ -26,8 +26,9 @@ namespace BaseGames.Enemies.Behaviors [Header("演出期间")] [Tooltip("演出期间停用的受击框(防止演出中被打断或二次受伤);对象池复用时 OnSpawn 自动恢复")] [SerializeField] private HurtBox[] _hurtBoxesToDisable; - [Tooltip("演出开始时停止行为树(防止 BT 继续 Tick 覆盖演出动画)")] - [SerializeField] private bool _stopBehaviorTree = true; + [UnityEngine.Serialization.FormerlySerializedAs("_stopBehaviorTree")] + [Tooltip("死亡演出开始时通知决策层终止,防止 AI 继续覆盖演出")] + [SerializeField] private bool _stopDecisionLayer = true; [Tooltip("演出开始时停止移动")] [SerializeField] private bool _stopMovement = true; @@ -60,7 +61,7 @@ namespace BaseGames.Enemies.Behaviors private IEnumerator Sequence(Action onComplete) { - if (_stopBehaviorTree) _enemy?.StopBehaviorTree(); + if (_stopDecisionLayer) _enemy?.NotifyDecisionStop(); if (_stopMovement) _enemy?.StopMovement(); SetHurtBoxesEnabled(false); diff --git a/Assets/_Game/Scripts/Enemies/Boss/ChaoFengBoss.cs b/Assets/_Game/Scripts/Enemies/Boss/ChaoFengBoss.cs index 7c094d55..4bfad656 100644 --- a/Assets/_Game/Scripts/Enemies/Boss/ChaoFengBoss.cs +++ b/Assets/_Game/Scripts/Enemies/Boss/ChaoFengBoss.cs @@ -18,7 +18,7 @@ namespace BaseGames.Enemies.Boss /// 1. BossBase.BeginPhaseTransition → OnBeginPhaseTransition(1) 立即播放过渡动画 + 开始浮空 /// 2. 无敌期结束(≥ _riseDuration+buffer)→ BossBase.EnterPhase(1) 广播阶段切换事件 /// - /// ⚠️ 动画由本脚本通过 Animancer.Play() 完整控制,不在 BD 中调用 BD_PlayAnimation。 + /// ⚠️ 动画由本脚本通过 Animancer.Play() 完整控制,不由 AI 决策层驱动播放。 /// public class ChaoFengBoss : BossBase { @@ -57,7 +57,7 @@ namespace BaseGames.Enemies.Boss /// /// 阶段过渡开始时立即播放过渡动画并启动浮空协程。 - /// invincibleDuration 需在 BD_BossPhaseTransition 中配置为 ≥ _riseDuration + 缓冲(约 2.0s)。 + /// invincibleDuration 需在触发阶段过渡的调用处配置为 ≥ _riseDuration + 缓冲(约 2.0s)。 /// protected override void OnBeginPhaseTransition(int targetPhase) { @@ -185,7 +185,7 @@ namespace BaseGames.Enemies.Boss private IEnumerator DefeatSequence() { - StopBehaviorTree(); + NotifyDecisionStop(); _knockdownCounter?.ForceEnd(); // Phase 2(空中)先落地 diff --git a/Assets/_Game/Scripts/Enemies/EnemyBase.cs b/Assets/_Game/Scripts/Enemies/EnemyBase.cs index fd5da26b..f51e2055 100644 --- a/Assets/_Game/Scripts/Enemies/EnemyBase.cs +++ b/Assets/_Game/Scripts/Enemies/EnemyBase.cs @@ -11,8 +11,8 @@ namespace BaseGames.Enemies { /// /// 敌人基类(架构 07_EnemyModule §1)。 - /// 实现 IDamageable,为 Behavior Designer 任务提供统一虚方法接口。 - /// 包含:BD 接口、受击、死亡流程。 + /// 实现 IDamageable,为 AI 决策层提供统一虚方法接口。 + /// 包含:决策层接口、受击、死亡流程。 /// ⚠️ _nav 字段类型为 IEnemyNavigator(在 BaseGames.Enemies.Navigation 中实现具体类)。 /// 实现 IPoolable:配合 PooledObject 支持对象池复用,避免频繁 Destroy/Instantiate。 /// @@ -49,7 +49,7 @@ namespace BaseGames.Enemies [SerializeField] private Collider2D _bodyCollider; [Header("区域(可选)")] - [Tooltip("地图固定巡逻/追击区域;配置后 BD_ChasePlayer 以区域边界替代 MaxChaseDistance,BD_ReturnToHome 归位至区域中心。留空则沿用出生点 + MaxChaseDistance 旧逻辑。")] + [Tooltip("地图固定巡逻/追击区域;配置后追击以区域边界替代 MaxChaseDistance,归位至区域中心。留空则沿用出生点 + MaxChaseDistance 旧逻辑。")] [SerializeField] private EnemyPatrolZone _patrolZone; [Header("事件频道")] @@ -97,18 +97,18 @@ namespace BaseGames.Enemies public EnemyStateType CurrentState => _currentState; // ── 导航语义(归位 / 搜查)──────────────────────────────────────────── - /// Awake/Start 时记录的初始世界坐标,供 BD_ReturnToHome 归位使用。 + /// Awake/Start 时记录的初始世界坐标,供归位行为使用。 public Vector2 HomePosition { get; private set; } /// /// 玩家最后一次可见的世界坐标。 - /// 由 BD_ChasePlayer 在持有视线时每帧更新;视线丢失后保留最后记录值供 BD_InvestigateLastKnown 使用。 + /// 由追击行为在持有视线时每帧更新;视线丢失后保留最后记录值供「搜查最后已知位置」行为使用。 /// public Vector2 LastKnownPlayerPosition { get; set; } /// /// 地图固定巡逻/追击区域(可选)。 - /// 配置后 BD_ChasePlayer 以区域边界为追击上限;BD_ReturnToHome 归位至区域中心。 + /// 配置后追击以区域边界为上限;归位至区域中心。 /// 未配置时退回旧逻辑(HomePosition + MaxChaseDistance)。 /// public EnemyPatrolZone PatrolZone => _patrolZone; @@ -222,7 +222,7 @@ namespace BaseGames.Enemies public IEnemyLocomotion Locomotion => _locomotion ?? (_locomotion = GetComponentInChildren(true)); public EnemyMovement Movement => _movement; public EnemyStats Stats => _stats; - /// 敌人配置 SO,供 BD Task / 状态对象读取配置数据(如 knockUpDuration)。 + /// 敌人配置 SO,供 AI 决策层 / 状态对象读取配置数据(如 knockUpDuration)。 public EnemyStatsSO StatsSO => _statsSO; public AnimancerComponent Animancer => _animancer; public EnemyAnimationConfigSO AnimConfig => _animConfig; @@ -234,9 +234,9 @@ namespace BaseGames.Enemies private Abilities.EnemyAttackSelector _attackSelector; /// 身体碰撞体几何的唯一权威查询口。移动/导航/能力一律经此获取身体尺寸。 public IEnemyBody Body => _body ??= new EnemyBody(gameObject, _bodyCollider); - /// 由 _onPlayerSpawned 事件缓存的玩家 Transform,供 BD 任务读取。 + /// 由 _onPlayerSpawned 事件缓存的玩家 Transform,供 AI 决策层读取。 public Transform PlayerTransform => _playerTransform; - /// 感知 Hub;供 BD 任务及 QuotaManager 暂停/恢复感知使用。 + /// 感知 Hub;供 AI 决策层及 QuotaManager 暂停/恢复感知使用。 public Perception.IPerceptionSystem SensorHub => _sensorHub; private Perception.IPerceptionSystem _sensorHub; /// 威胁评估器(可选):为原始 LOS 结果叠加反应延迟,使感知更自然。 @@ -253,7 +253,7 @@ namespace BaseGames.Enemies public bool IsEngaged { get; private set; } public void SetEngaged(bool engaged) => IsEngaged = engaged; - // ── BD 行为树接口(虚方法)──────────────────────────────────────── + // ── AI 决策层接口(虚方法)────────────────────────────────────── public virtual void MoveTo(Vector2 target) => _nav?.MoveTowards(target); @@ -402,37 +402,16 @@ namespace BaseGames.Enemies } // ── 弹反(Parry)响应 ────────────────────────────────────────────── - private bool _wasParried; - private float _parryTimestamp; - // BD 树因阶段切换/死亡未能消费弹反事件时,超过此时长自动过期 - private const float ParryEventTTL = 2f; /// - /// 消费弹反事件标志(读取并清除)。 - /// BD_OnParried Conditional Task 在每次 Tick 时调用此方法。 - /// 若 BD 树因阶段切换或死亡未能及时消费,超过 TTL 后自动过期返回 false。 - /// - public bool ConsumeParryEvent() - { - if (!_wasParried) return false; - if (Time.time - _parryTimestamp > ParryEventTTL) - { - _wasParried = false; - return false; - } - _wasParried = false; - return true; - } - - /// - /// 被弹反时调用:强制进入 Stagger 状态并在 秒后恢复。 - /// 由近战攻击碰到玩家弹反框时触发(例如 BossParryDetector 或通用 ParryDetector)。 + /// 被弹反时调用:强制进入 Stagger 并在 staggerDuration 秒后恢复。 + /// Stagger 期间 IsControllable 为 false,AI 决策自动让位——不需要额外的 AI 信号。 + /// ⚠️ 目前**零调用者**:弹反管线(HurtBox → ParrySystem.ConsumeParry)拿不到攻击者引用, + /// 接线是一件独立任务(DamageInfo 加 attacker,或弹反成功时回调发起攻击的 HitBox)。 /// public virtual void ReceiveParry(float staggerDuration = 0.5f) { if (!IsAlive) return; - _wasParried = true; - _parryTimestamp = Time.time; ForceState(EnemyStateType.Stagger); _abilities.InterruptAll(InterruptReason.Stagger); ScheduleStateRecovery(EnemyStateType.Stagger, staggerDuration); @@ -626,7 +605,7 @@ namespace BaseGames.Enemies protected virtual void Start() { - // 记录出生位置,供 BD_ReturnToHome 归位使用 + // 记录出生位置,供归位行为使用 HomePosition = transform.position; LastKnownPlayerPosition = transform.position; @@ -659,11 +638,11 @@ namespace BaseGames.Enemies protected virtual void OnDestroy() { } /// - /// 通知决策层终止(死亡演出 / 出场演出等期间调用,防止决策继续覆盖演出逻辑)。 - /// 语义为"通知决策层终止",与 PerformDeath 的 Died 信号幂等(重复 Died 无害)。 + /// 通知决策层终止(死亡演出 / 出场演出期间调用,防止决策继续覆盖演出逻辑)。 + /// 与 PerformDeath 发的 Died 信号幂等(重复 Died 无害)。 /// 供配置型行为组件(如 EnemyDeathSequence)调用,故为 public。 /// - public void StopBehaviorTree() + public void NotifyDecisionStop() { _brain?.Send(BaseGames.AI.AiSignal.Died); } @@ -752,7 +731,6 @@ namespace BaseGames.Enemies // 重置对象池复用相关的运行时感知数据 // 注意:_playerTransform 不重置(场景中玩家仍存在),只重置追踪历史 LastKnownPlayerPosition = transform.position; - _wasParried = false; _deathSequenceActive = false; // 重置生命值