using UnityEngine; using Animancer; using BaseGames.Combat; namespace BaseGames.Enemies { /// /// 敌人基类(架构 07_EnemyModule §1)。 /// 实现 IDamageable,为 Behavior Designer 任务提供统一虚方法接口。 /// Phase 1 实现:完整骨架,BD 接口、受击、死亡流程。 /// ⚠️ _nav 字段类型为 IPathAgent(在 BaseGames.Enemies.Navigation 中实现具体类)。 /// public class EnemyBase : MonoBehaviour, IDamageable { [Header("配置 SO")] [SerializeField] protected EnemyStatsSO _statsSO; [SerializeField] protected EnemyAnimationConfigSO _animConfig; [Header("子组件(Prefab Inspector 绑定)")] [SerializeField] protected EnemyStats _stats; [SerializeField] protected EnemyMovement _movement; [SerializeField] protected EnemyCombat _combat; [SerializeField] protected AnimancerComponent _animancer; [SerializeField] protected EnemyFeedback _feedback; [SerializeField] protected HurtBox _hurtBox; [Header("事件频道")] [SerializeField] private BaseGames.Core.Events.TransformEventChannelSO _onEnemyDied; // ── 导航代理(IPathAgent;由 EnemyNavAgent 实现)─────────────────── // Phase 1:通过接口引用,避免对 Navigation 程序集的直接依赖。 // 由子类 / Inspector 注入,或者运行时 GetComponent() 获取。 protected IPathAgent _nav; // ── 状态 ────────────────────────────────────────────────────────── private EnemyStateType _currentState; public EnemyStateType CurrentState => _currentState; // ── IDamageable ─────────────────────────────────────────────────── public bool IsInvincible => _currentState == EnemyStateType.Dead; public int Defense => _stats != null ? _stats.Defense : 0; public void TakeDamage(DamageInfo info) { if (_currentState == EnemyStateType.Dead) return; _stats?.TakeDamage(info.FinalDamage); _feedback?.OnHit(info); if (_stats != null && _stats.CurrentHP <= 0) { Die(); return; } // Phase 2:根据霸体结果选 Stagger / Hurt ForceState(EnemyStateType.Hurt); } // ── BD 行为树接口(虚方法)──────────────────────────────────────── public virtual void MoveTo(Vector2 target) => _nav?.RequestMoveTo(target); public virtual void MoveInDirection(float dir) => _movement?.MoveHorizontal(dir); public virtual void StopMovement() { _nav?.StopNavigation(); _movement?.StopHorizontal(); } public virtual void BeginAttack(AttackType type) { _combat?.StartAttack(type); _stats?.ResetAttackCooldown(); } public virtual bool CanAttack() => _stats != null && _stats.AttackCooldownTimer <= 0f; public virtual bool IsPlayerInRange(float range) => _stats != null && _stats.DistanceToPlayer <= range; public virtual void FacePlayer() { if (_playerTransform != null) _movement?.FaceTarget(_playerTransform.position); } public virtual void Knockback(DamageInfo info) { if (info.Flags.HasFlag(DamageFlags.NoKnockback)) return; _movement?.ApplyKnockback(info.KnockbackDirection, info.KnockbackForce); } // ── 状态控制 ────────────────────────────────────────────────────── public void ForceState(EnemyStateType newState) { _currentState = newState; // Phase 2:根据状态播放对应动画 / 触发硬直计时 } // ── Unity 生命周期 ──────────────────────────────────────────────── protected virtual void Awake() { _nav = GetComponent() ?? new NullPathAgent(); if (_stats != null && _statsSO != null) _stats.Initialize(_statsSO); // Phase 1:简单查找玩家;Phase 2 改为事件频道订阅 var playerGO = GameObject.FindWithTag("Player"); if (playerGO != null) _playerTransform = playerGO.transform; } protected virtual void Update() { _stats?.TickAttackCooldown(Time.deltaTime); if (_playerTransform != null && _stats != null) _stats.DistanceToPlayer = Vector2.Distance(transform.position, _playerTransform.position); } protected virtual void Start() { // 播放 Idle 动画(若 Animancer 和配置都就绪) if (_animancer != null && _animConfig != null && _animConfig.Idle != null) _animancer.Play(_animConfig.Idle); } // ── 内部 ────────────────────────────────────────────────────────── private Transform _playerTransform; protected virtual void Die() { if (_currentState == EnemyStateType.Dead) return; ForceState(EnemyStateType.Dead); // 禁用所有碰撞体 foreach (var col in GetComponentsInChildren()) col.enabled = false; // 播放死亡动画 if (_animancer != null && _animConfig != null && _animConfig.Dead != null) { var state = _animancer.Play(_animConfig.Dead); state.Events(this).OnEnd = () => Destroy(gameObject); } else { Destroy(gameObject, 1.5f); } _feedback?.OnDeath(); _onEnemyDied?.Raise(transform); } } // ── 枚举(架构 07 §1)──────────────────────────────────────────────── public enum EnemyStateType { Controlled, Hurt, Stagger, Dead } public enum AttackType { Melee, Ranged, Special } }