feat(enemy): EnemyBase 持有身体几何权威(_bodyCollider + Body),Awake/OnValidate 双重校验
This commit is contained in:
@@ -43,6 +43,11 @@ namespace BaseGames.Enemies
|
||||
[SerializeField] protected EnemyFeedback _feedback;
|
||||
[SerializeField] protected HurtBox _hurtBox;
|
||||
|
||||
[Header("身体碰撞体(唯一权威源)")]
|
||||
[Tooltip("用于身体几何(宽高/边缘/探测起点)的碰撞体。留空 = 使用本物体上的 Collider2D。" +
|
||||
"移动探测、导航内缩、冲刺终点等全部以此为准,不要在各处自行取碰撞体。")]
|
||||
[SerializeField] private Collider2D _bodyCollider;
|
||||
|
||||
[Header("区域(可选)")]
|
||||
[Tooltip("地图固定巡逻/追击区域;配置后 BD_ChasePlayer 以区域边界替代 MaxChaseDistance,BD_ReturnToHome 归位至区域中心。留空则沿用出生点 + MaxChaseDistance 旧逻辑。")]
|
||||
[SerializeField] private EnemyPatrolZone _patrolZone;
|
||||
@@ -69,6 +74,9 @@ namespace BaseGames.Enemies
|
||||
// 碰撞体缓存:Awake 时收集一次,避免 Die()/OnSpawn() 中频繁 GetComponentsInChildren 分配
|
||||
private Collider2D[] _colliders;
|
||||
|
||||
// 身体几何权威(懒创建;OnValidate 改引用后置空重建)
|
||||
private EnemyBody _body;
|
||||
|
||||
// ── 对象池支持 ─────────────────────────────────────────────────────
|
||||
/// <summary>
|
||||
/// 本 GameObject 上的 PooledObject 组件(可选)。
|
||||
@@ -224,6 +232,8 @@ namespace BaseGames.Enemies
|
||||
/// <summary>攻击选择器(从已注册能力里筛出 category==Attack 的候选,Awake 时构建)。</summary>
|
||||
public Abilities.EnemyAttackSelector AttackSelector => _attackSelector;
|
||||
private Abilities.EnemyAttackSelector _attackSelector;
|
||||
/// <summary>身体碰撞体几何的唯一权威查询口。移动/导航/能力一律经此获取身体尺寸。</summary>
|
||||
public IEnemyBody Body => _body ??= new EnemyBody(gameObject, _bodyCollider);
|
||||
/// <summary>由 _onPlayerSpawned 事件缓存的玩家 Transform,供 BD 任务读取。</summary>
|
||||
public Transform PlayerTransform => _playerTransform;
|
||||
/// <summary>感知 Hub;供 BD 任务及 QuotaManager 暂停/恢复感知使用。</summary>
|
||||
@@ -543,6 +553,11 @@ namespace BaseGames.Enemies
|
||||
BuildAttackSelector();
|
||||
_colliders = GetComponentsInChildren<Collider2D>(true);
|
||||
|
||||
// 身体几何权威校验:解析不到碰撞体 → 显式报错(根因暴露,不静默兜底)
|
||||
if (Body.Collider == null)
|
||||
Debug.LogError($"[EnemyBase] {name} 找不到身体碰撞体:请在 Inspector 指定 _bodyCollider," +
|
||||
"或确保本物体上挂有 Collider2D。移动探测/导航内缩将不可用。", this);
|
||||
|
||||
// 收集配置型行为模块(零代码扩展点)
|
||||
_deathSequence = GetComponentInChildren<Behaviors.IEnemyDeathSequence>(true);
|
||||
GetComponentsInChildren(true, _spawnHandlers);
|
||||
@@ -757,6 +772,7 @@ namespace BaseGames.Enemies
|
||||
|
||||
protected virtual void OnValidate()
|
||||
{
|
||||
_body = null; // 身体碰撞体引用可能在 Inspector 被改,缓存无条件失效(与警告抑制无关)
|
||||
if (SuppressValidationWarnings) return;
|
||||
if (_statsSO == null)
|
||||
Debug.LogWarning($"[EnemyBase] {gameObject.name} 缺少 EnemyStatsSO 配置(运行时会 NullRef)。", this);
|
||||
@@ -764,6 +780,8 @@ namespace BaseGames.Enemies
|
||||
Debug.LogWarning($"[EnemyBase] {gameObject.name} 未绑定 EnemyStats 组件引用。", this);
|
||||
if (_animancer == null)
|
||||
Debug.LogWarning($"[EnemyBase] {gameObject.name} 未绑定 AnimancerComponent 引用。", this);
|
||||
if (_bodyCollider == null && GetComponent<Collider2D>() == null)
|
||||
Debug.LogWarning($"[EnemyBase] {gameObject.name} 找不到身体碰撞体(未指定 _bodyCollider 且本物体无 Collider2D)。", this);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user