feat(enemy): ICombatant 增加 HasEligibleAttack/UseBestAttack + EnemyBase 构建选择器

This commit is contained in:
2026-07-24 12:20:54 +08:00
parent 04a267b69f
commit 702df35efd
4 changed files with 60 additions and 0 deletions
+28
View File
@@ -221,6 +221,9 @@ namespace BaseGames.Enemies
/// <summary>能力注册表(架构 §8.3)。Awake 时自动收集所有 EnemyAbilityBase 组件。</summary>
public EnemyAbilityRegistry Abilities => _abilities;
private readonly EnemyAbilityRegistry _abilities = new EnemyAbilityRegistry();
/// <summary>攻击选择器(从已注册能力里筛出 category==Attack 的候选,Awake 时构建)。</summary>
public Abilities.EnemyAttackSelector AttackSelector => _attackSelector;
private Abilities.EnemyAttackSelector _attackSelector;
/// <summary>由 _onPlayerSpawned 事件缓存的玩家 Transform,供 BD 任务读取。</summary>
public Transform PlayerTransform => _playerTransform;
/// <summary>感知 Hub;供 BD 任务及 QuotaManager 暂停/恢复感知使用。</summary>
@@ -537,6 +540,7 @@ namespace BaseGames.Enemies
_pooledObject = GetComponent<PooledObject>();
_brain = GetComponent<EnemyAiBrain>();
_abilities.CollectFrom(gameObject);
BuildAttackSelector();
_colliders = GetComponentsInChildren<Collider2D>(true);
// 收集配置型行为模块(零代码扩展点)
@@ -552,6 +556,30 @@ namespace BaseGames.Enemies
// 订阅在 OnEnable 中处理
}
/// <summary>
/// 从已注册能力里收集 category==Attack 的候选,构建攻击选择器。
/// 根因校验:攻击招 rangeRadius<=0(永远够不着)显式报错,不静默兜底。
/// </summary>
private void BuildAttackSelector()
{
var candidates = new System.Collections.Generic.List<Abilities.IAttackCandidate>();
var all = _abilities?.All;
if (all != null)
{
for (int i = 0; i < all.Count; i++)
{
var ab = all[i];
if (ab == null || ab.Config == null) continue;
if (ab.Config.category != Abilities.AbilityCategory.Attack) continue;
if (ab.Config.rangeRadius <= 0f)
Debug.LogError($"[EnemyBase] 攻击招 '{ab.Config.abilityId}' 的 rangeRadius<=0" +
"永远够不着玩家。请在其 EnemyAbilitySO 上配置攻击触发半径。", ab);
candidates.Add(ab);
}
}
_attackSelector = new Abilities.EnemyAttackSelector(candidates);
}
protected virtual void Update()
{
_stats?.TickAttackCooldown(Time.deltaTime);