refactor(enemy): 敌人专属子类改为零代码配置型行为组件
This commit is contained in:
@@ -27,6 +27,12 @@ namespace BaseGames.Enemies
|
||||
/// <summary>死亡时触发(ChallengeRoomManager 波次结算用)。</summary>
|
||||
public event System.Action OnDied;
|
||||
|
||||
/// <summary>
|
||||
/// 对象池取出并完成 <see cref="OnSpawn"/> 重置后触发。
|
||||
/// 配置型出生行为组件(如 EnemyAbilityTrigger)订阅此事件,实现零代码出生触发。
|
||||
/// </summary>
|
||||
public event System.Action Spawned;
|
||||
|
||||
[Header("配置 SO")]
|
||||
[SerializeField] protected EnemyStatsSO _statsSO;
|
||||
[SerializeField] protected EnemyAnimationConfigSO _animConfig;
|
||||
@@ -83,6 +89,14 @@ namespace BaseGames.Enemies
|
||||
/// </summary>
|
||||
private PooledObject _pooledObject;
|
||||
|
||||
// ── 配置型行为模块(零代码)─────────────────────────────────────────
|
||||
// 可选挂载的通用行为组件,替代过去的每敌人专属子类。Awake 时收集一次。
|
||||
private Behaviors.IEnemyDeathSequence _deathSequence;
|
||||
private readonly System.Collections.Generic.List<Behaviors.IEnemySpawnEventHandler> _spawnHandlers
|
||||
= new System.Collections.Generic.List<Behaviors.IEnemySpawnEventHandler>(2);
|
||||
// 死亡前摇演出进行中:纳入 IsInvincible,并阻止重复触发 Die。
|
||||
private bool _deathSequenceActive;
|
||||
|
||||
// ── 状态 ──────────────────────────────────────────────────────────
|
||||
private EnemyStateType _currentState;
|
||||
public EnemyStateType CurrentState => _currentState;
|
||||
@@ -129,7 +143,7 @@ namespace BaseGames.Enemies
|
||||
= new System.Collections.Generic.Dictionary<EnemyStateType, IEnemyState>();
|
||||
// ── IDamageable ───────────────────────────────────────────────────
|
||||
public bool IsAlive => _currentState != EnemyStateType.Dead;
|
||||
public virtual bool IsInvincible => _currentState == EnemyStateType.Dead;
|
||||
public virtual bool IsInvincible => _currentState == EnemyStateType.Dead || _deathSequenceActive;
|
||||
public int Defense => _stats != null ? _stats.Defense : 0;
|
||||
|
||||
public void TakeDamage(DamageInfo info)
|
||||
@@ -478,8 +492,17 @@ namespace BaseGames.Enemies
|
||||
|
||||
// ── 动画事件钩子(由 EnemyAnimationEvents 调用)────────────────────
|
||||
|
||||
/// <summary>生成弹幕 / 技能投射物。payload 为配置 Id,由子类查表实现。</summary>
|
||||
public virtual void SpawnProjectile(string payload) { }
|
||||
/// <summary>
|
||||
/// 生成弹幕 / 技能投射物(由动画事件 SpawnProjectile 触发)。
|
||||
/// 基类实现:路由到所有挂载的 <see cref="Behaviors.IEnemySpawnEventHandler"/> 组件
|
||||
/// (如 EnemySpawnerOnEvent),由组件按 payload 自行匹配并生成——实现零代码生成配置。
|
||||
/// 子类(如 RangedEnemy / ChaoFengBoss)可重写以自定义发射逻辑。
|
||||
/// </summary>
|
||||
public virtual void SpawnProjectile(string payload)
|
||||
{
|
||||
for (int i = 0; i < _spawnHandlers.Count; i++)
|
||||
_spawnHandlers[i]?.HandleSpawn(payload);
|
||||
}
|
||||
|
||||
/// <summary>切换二阶段形态(Boss 等特殊敌人重写此方法)。</summary>
|
||||
public virtual void TriggerPhaseTwo() { }
|
||||
@@ -560,6 +583,10 @@ namespace BaseGames.Enemies
|
||||
_abilities.CollectFrom(gameObject);
|
||||
_colliders = GetComponentsInChildren<Collider2D>(true);
|
||||
|
||||
// 收集配置型行为模块(零代码扩展点)
|
||||
_deathSequence = GetComponentInChildren<Behaviors.IEnemyDeathSequence>(true);
|
||||
GetComponentsInChildren(true, _spawnHandlers);
|
||||
|
||||
Debug.Assert(_statsSO != null, "[EnemyBase] _statsSO 未赋值,请在 Prefab Inspector 中指定 EnemyStatsSO。", this);
|
||||
Debug.Assert(_stats != null, "[EnemyBase] _stats 未绑定,请在 Prefab Inspector 中绑定 EnemyStats 组件。", this);
|
||||
Debug.Assert(_movement != null, "[EnemyBase] _movement 未找到,请确保同 GameObject 上挂有 EnemyMovement 组件。", this);
|
||||
@@ -667,19 +694,46 @@ namespace BaseGames.Enemies
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// 停止行为树(子类 Die() 预演出阶段可调用,防止 BT 继续 Tick 覆盖演出逻辑)。
|
||||
/// 内部使用 #if GRAPH_DESIGNER 保护,子类无需处理条件编译。
|
||||
/// 停止行为树(死亡演出 / 出场演出等期间调用,防止 BT 继续 Tick 覆盖演出逻辑)。
|
||||
/// 内部使用 #if GRAPH_DESIGNER 保护,调用方无需处理条件编译。
|
||||
/// 供配置型行为组件(如 EnemyDeathSequence)调用,故为 public。
|
||||
/// </summary>
|
||||
protected void StopBehaviorTree()
|
||||
public void StopBehaviorTree()
|
||||
{
|
||||
#if GRAPH_DESIGNER
|
||||
_behaviorTree?.StopBehavior();
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 死亡入口。若挂载了 <see cref="Behaviors.IEnemyDeathSequence"/> 死亡演出组件,
|
||||
/// 则先委托其播放无敌前摇(期间 <see cref="IsInvincible"/> 为 true),演出结束后回调
|
||||
/// <see cref="PerformDeath"/> 执行真正的死亡清理;否则直接清理。
|
||||
/// 子类(如 BossBase)重写时仍调用 base.Die() 即可获得此委托行为。
|
||||
/// </summary>
|
||||
protected virtual void Die()
|
||||
{
|
||||
if (_currentState == EnemyStateType.Dead || _deathSequenceActive) return;
|
||||
|
||||
if (_deathSequence != null)
|
||||
{
|
||||
_deathSequenceActive = true; // 演出期间纳入 IsInvincible,阻止重复 Die
|
||||
_deathSequence.Play(PerformDeath);
|
||||
return;
|
||||
}
|
||||
|
||||
PerformDeath();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 实际死亡清理:切 Dead 终态、清状态效果、中断能力、关碰撞体、播死亡动画、
|
||||
/// 归还对象池 / 销毁、广播死亡事件。由 <see cref="Die"/> 直接调用,
|
||||
/// 或由死亡演出组件在前摇结束后回调。
|
||||
/// </summary>
|
||||
protected void PerformDeath()
|
||||
{
|
||||
if (_currentState == EnemyStateType.Dead) return;
|
||||
_deathSequenceActive = false;
|
||||
ForceState(EnemyStateType.Dead);
|
||||
|
||||
// 死亡时清除所有状态效果
|
||||
@@ -733,6 +787,7 @@ namespace BaseGames.Enemies
|
||||
// 注意:_playerTransform 不重置(场景中玩家仍存在),只重置追踪历史
|
||||
LastKnownPlayerPosition = transform.position;
|
||||
_wasParried = false;
|
||||
_deathSequenceActive = false;
|
||||
|
||||
// 重置生命值
|
||||
if (_stats != null && _statsSO != null)
|
||||
@@ -744,6 +799,9 @@ namespace BaseGames.Enemies
|
||||
#if GRAPH_DESIGNER
|
||||
_behaviorTree?.StartBehavior();
|
||||
#endif
|
||||
|
||||
// 通知配置型出生行为组件(如 EnemyAbilityTrigger)执行出生触发逻辑
|
||||
Spawned?.Invoke();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user