refactor(enemy): 清行为树债——StopBehaviorTree 改名,删 ConsumeParryEvent
StopBehaviorTree → NotifyDecisionStop(方法体早已只是发 Died 信号)。 EnemyDeathSequence 的 _stopBehaviorTree 字段同步改名,带 FormerlySerializedAs 保值。 ConsumeParryEvent 及其 TTL 状态删除:零调用者,且 ForceState(Stagger) + IsControllable 让位门已是更优表达,不需要第二条受击通道。 顺带清掉这三个文件里残留的行为树插件措辞(BD_* / BD Task / 停行为树)。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -9,7 +9,7 @@ namespace BaseGames.Enemies.Behaviors
|
||||
/// <summary>
|
||||
/// 死亡前摇无敌演出(零代码替代每敌人专属的 <c>Die()</c> 重写)。
|
||||
/// <para>
|
||||
/// <see cref="EnemyBase.Die"/> 会委托本组件:停行为树 / 停移动、停用受击框,播放前摇动画并等待,
|
||||
/// <see cref="EnemyBase.Die"/> 会委托本组件:通知决策层终止 / 停移动、停用受击框,播放前摇动画并等待,
|
||||
/// 期间敌人处于无敌(<see cref="EnemyBase.IsInvincible"/>),演出结束后回调真正的死亡清理。
|
||||
/// 前摇动画上可放置 SpawnProjectile 动画事件,配合 <see cref="EnemySpawnerOnEvent"/> 在演出中生成小怪。
|
||||
/// </para>
|
||||
@@ -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);
|
||||
|
||||
@@ -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 决策层驱动播放。
|
||||
/// </summary>
|
||||
public class ChaoFengBoss : BossBase
|
||||
{
|
||||
@@ -57,7 +57,7 @@ namespace BaseGames.Enemies.Boss
|
||||
|
||||
/// <summary>
|
||||
/// 阶段过渡开始时立即播放过渡动画并启动浮空协程。
|
||||
/// invincibleDuration 需在 BD_BossPhaseTransition 中配置为 ≥ _riseDuration + 缓冲(约 2.0s)。
|
||||
/// invincibleDuration 需在触发阶段过渡的调用处配置为 ≥ _riseDuration + 缓冲(约 2.0s)。
|
||||
/// </summary>
|
||||
protected override void OnBeginPhaseTransition(int targetPhase)
|
||||
{
|
||||
@@ -185,7 +185,7 @@ namespace BaseGames.Enemies.Boss
|
||||
|
||||
private IEnumerator DefeatSequence()
|
||||
{
|
||||
StopBehaviorTree();
|
||||
NotifyDecisionStop();
|
||||
_knockdownCounter?.ForceEnd();
|
||||
|
||||
// Phase 2(空中)先落地
|
||||
|
||||
@@ -11,8 +11,8 @@ namespace BaseGames.Enemies
|
||||
{
|
||||
/// <summary>
|
||||
/// 敌人基类(架构 07_EnemyModule §1)。
|
||||
/// 实现 IDamageable,为 Behavior Designer 任务提供统一虚方法接口。
|
||||
/// 包含:BD 接口、受击、死亡流程。
|
||||
/// 实现 IDamageable,为 AI 决策层提供统一虚方法接口。
|
||||
/// 包含:决策层接口、受击、死亡流程。
|
||||
/// ⚠️ _nav 字段类型为 IEnemyNavigator(在 BaseGames.Enemies.Navigation 中实现具体类)。
|
||||
/// 实现 IPoolable:配合 PooledObject 支持对象池复用,避免频繁 Destroy/Instantiate。
|
||||
/// </summary>
|
||||
@@ -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;
|
||||
|
||||
// ── 导航语义(归位 / 搜查)────────────────────────────────────────────
|
||||
/// <summary>Awake/Start 时记录的初始世界坐标,供 BD_ReturnToHome 归位使用。</summary>
|
||||
/// <summary>Awake/Start 时记录的初始世界坐标,供归位行为使用。</summary>
|
||||
public Vector2 HomePosition { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 玩家最后一次可见的世界坐标。
|
||||
/// 由 BD_ChasePlayer 在持有视线时每帧更新;视线丢失后保留最后记录值供 BD_InvestigateLastKnown 使用。
|
||||
/// 由追击行为在持有视线时每帧更新;视线丢失后保留最后记录值供「搜查最后已知位置」行为使用。
|
||||
/// </summary>
|
||||
public Vector2 LastKnownPlayerPosition { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 地图固定巡逻/追击区域(可选)。
|
||||
/// 配置后 BD_ChasePlayer 以区域边界为追击上限;BD_ReturnToHome 归位至区域中心。
|
||||
/// 配置后追击以区域边界为上限;归位至区域中心。
|
||||
/// 未配置时退回旧逻辑(HomePosition + MaxChaseDistance)。
|
||||
/// </summary>
|
||||
public EnemyPatrolZone PatrolZone => _patrolZone;
|
||||
@@ -222,7 +222,7 @@ namespace BaseGames.Enemies
|
||||
public IEnemyLocomotion Locomotion => _locomotion ?? (_locomotion = GetComponentInChildren<IEnemyLocomotion>(true));
|
||||
public EnemyMovement Movement => _movement;
|
||||
public EnemyStats Stats => _stats;
|
||||
/// <summary>敌人配置 SO,供 BD Task / 状态对象读取配置数据(如 knockUpDuration)。</summary>
|
||||
/// <summary>敌人配置 SO,供 AI 决策层 / 状态对象读取配置数据(如 knockUpDuration)。</summary>
|
||||
public EnemyStatsSO StatsSO => _statsSO;
|
||||
public AnimancerComponent Animancer => _animancer;
|
||||
public EnemyAnimationConfigSO AnimConfig => _animConfig;
|
||||
@@ -234,9 +234,9 @@ namespace BaseGames.Enemies
|
||||
private Abilities.EnemyAttackSelector _attackSelector;
|
||||
/// <summary>身体碰撞体几何的唯一权威查询口。移动/导航/能力一律经此获取身体尺寸。</summary>
|
||||
public IEnemyBody Body => _body ??= new EnemyBody(gameObject, _bodyCollider);
|
||||
/// <summary>由 _onPlayerSpawned 事件缓存的玩家 Transform,供 BD 任务读取。</summary>
|
||||
/// <summary>由 _onPlayerSpawned 事件缓存的玩家 Transform,供 AI 决策层读取。</summary>
|
||||
public Transform PlayerTransform => _playerTransform;
|
||||
/// <summary>感知 Hub;供 BD 任务及 QuotaManager 暂停/恢复感知使用。</summary>
|
||||
/// <summary>感知 Hub;供 AI 决策层及 QuotaManager 暂停/恢复感知使用。</summary>
|
||||
public Perception.IPerceptionSystem SensorHub => _sensorHub;
|
||||
private Perception.IPerceptionSystem _sensorHub;
|
||||
/// <summary>威胁评估器(可选):为原始 LOS 结果叠加反应延迟,使感知更自然。</summary>
|
||||
@@ -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;
|
||||
|
||||
/// <summary>
|
||||
/// 消费弹反事件标志(读取并清除)。
|
||||
/// BD_OnParried Conditional Task 在每次 Tick 时调用此方法。
|
||||
/// 若 BD 树因阶段切换或死亡未能及时消费,超过 TTL 后自动过期返回 false。
|
||||
/// </summary>
|
||||
public bool ConsumeParryEvent()
|
||||
{
|
||||
if (!_wasParried) return false;
|
||||
if (Time.time - _parryTimestamp > ParryEventTTL)
|
||||
{
|
||||
_wasParried = false;
|
||||
return false;
|
||||
}
|
||||
_wasParried = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 被弹反时调用:强制进入 Stagger 状态并在 <paramref name="staggerDuration"/> 秒后恢复。
|
||||
/// 由近战攻击碰到玩家弹反框时触发(例如 BossParryDetector 或通用 ParryDetector)。
|
||||
/// 被弹反时调用:强制进入 Stagger 并在 staggerDuration 秒后恢复。
|
||||
/// Stagger 期间 IsControllable 为 false,AI 决策自动让位——不需要额外的 AI 信号。
|
||||
/// ⚠️ 目前**零调用者**:弹反管线(HurtBox → ParrySystem.ConsumeParry)拿不到攻击者引用,
|
||||
/// 接线是一件独立任务(DamageInfo 加 attacker,或弹反成功时回调发起攻击的 HitBox)。
|
||||
/// </summary>
|
||||
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() { }
|
||||
|
||||
/// <summary>
|
||||
/// 通知决策层终止(死亡演出 / 出场演出等期间调用,防止决策继续覆盖演出逻辑)。
|
||||
/// 语义为"通知决策层终止",与 PerformDeath 的 Died 信号幂等(重复 Died 无害)。
|
||||
/// 通知决策层终止(死亡演出 / 出场演出期间调用,防止决策继续覆盖演出逻辑)。
|
||||
/// 与 PerformDeath 发的 Died 信号幂等(重复 Died 无害)。
|
||||
/// 供配置型行为组件(如 EnemyDeathSequence)调用,故为 public。
|
||||
/// </summary>
|
||||
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;
|
||||
|
||||
// 重置生命值
|
||||
|
||||
Reference in New Issue
Block a user