using UnityEngine; using BaseGames.AI; namespace BaseGames.Enemies { /// /// 敌人移动执行器:唯一的移动/朝向入口。AI 状态与能力经 IEnemyLocomotion /// 声明意图,本组件每帧把当前模式翻译为对 EnemyBase/IPathAgent 的调用。 /// 取代散落的 MoveTo/StopMovement/FacePlayer/FaceTarget 直调与三个协程能力。 /// [DisallowMultipleComponent] public sealed class EnemyLocomotion : MonoBehaviour, IEnemyLocomotion { [Header("巡逻策略(P6 实现 Pace/Waypoints;当前仅 Wander)")] [SerializeField] private PatrolStrategy _patrolStrategy = PatrolStrategy.Wander; private EnemyBase _enemy; private LocomotionMode _mode = LocomotionMode.Idle; private Transform _approachTarget; private Vector2 _facePoint; public LocomotionMode CurrentMode => _mode; public bool IsMoving => _enemy != null && _enemy.Nav != null && _enemy.Nav.IsMoving; private void Awake() { _enemy = GetComponentInParent(); if (_enemy == null) Debug.LogError("[EnemyLocomotion] 找不到 EnemyBase。", this); } // ── IEnemyLocomotion(声明意图,不立即 actuate 之外的副作用)── public void SetMode(LocomotionMode mode) { if (_mode == mode) return; _mode = mode; if (mode == LocomotionMode.Idle) _enemy?.StopMovement(); if (mode == LocomotionMode.Patrol && _enemy?.Stats != null) _enemy.Nav?.SetSpeed(_enemy.Stats.WalkSpeed); } public void Approach(Transform target) { _mode = LocomotionMode.Approach; _approachTarget = target; if (_enemy?.Stats != null) _enemy.Nav?.SetSpeed(_enemy.Stats.RunSpeed); } public void MoveTo(Vector2 point) { _mode = LocomotionMode.Approach; _approachTarget = null; _enemy?.MoveTo(point); } public void Face(Vector2 lookAt) { _mode = LocomotionMode.Face; _facePoint = lookAt; } public void Stop() { _mode = LocomotionMode.Idle; _enemy?.StopMovement(); } // ── 每帧把模式翻译成执行 ── private void Update() { if (_enemy == null) return; switch (_mode) { case LocomotionMode.Idle: break; // SetMode(Idle) 已停;保持 case LocomotionMode.Patrol: TickPatrol(); break; case LocomotionMode.Face: _enemy.StopMovement(); _enemy.FaceTarget(_facePoint); break; case LocomotionMode.Approach: if (_approachTarget != null) _enemy.MoveTo(_approachTarget.position); break; } } private void TickPatrol() { var nav = _enemy.Nav; if (nav == null) return; switch (_patrolStrategy) { case PatrolStrategy.Wander: if (!nav.IsMoving) nav.WalkToRandom(); break; // Pace / Waypoints:P6 实现 default: if (!nav.IsMoving) nav.WalkToRandom(); break; } } } }