feat(enemy): EnemyLocomotion 巡逻策略 Pace(踱步) + Waypoints(路点 loop/ping-pong)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -11,15 +11,23 @@ namespace BaseGames.Enemies
|
||||
[DisallowMultipleComponent]
|
||||
public sealed class EnemyLocomotion : MonoBehaviour, IEnemyLocomotion
|
||||
{
|
||||
[Header("巡逻策略(P6 实现 Pace/Waypoints;当前仅 Wander)")]
|
||||
[Header("巡逻策略(Wander/Pace/Waypoints)")]
|
||||
[SerializeField] private PatrolStrategy _patrolStrategy = PatrolStrategy.Wander;
|
||||
|
||||
[Header("Waypoints 策略参数")]
|
||||
[SerializeField] private Transform[] _waypoints;
|
||||
[SerializeField] private bool _pingPong;
|
||||
|
||||
private EnemyBase _enemy;
|
||||
private LocomotionMode _mode = LocomotionMode.Idle;
|
||||
private Transform _approachTarget;
|
||||
private Vector2 _facePoint;
|
||||
private LocomotionMode _gaitMode;
|
||||
private bool _gaitInit;
|
||||
private float _paceDir = 1f;
|
||||
private int _wpIndex = -1;
|
||||
private int _wpDir = 1;
|
||||
private bool _warnedNoWaypoints;
|
||||
|
||||
public LocomotionMode CurrentMode => _mode;
|
||||
public bool IsMoving => _enemy != null && _enemy.Nav != null && _enemy.Nav.IsMoving;
|
||||
@@ -96,17 +104,48 @@ namespace BaseGames.Enemies
|
||||
|
||||
private void TickPatrol()
|
||||
{
|
||||
var nav = _enemy.Nav;
|
||||
if (nav == null) return;
|
||||
switch (_patrolStrategy)
|
||||
{
|
||||
case PatrolStrategy.Wander:
|
||||
if (!nav.IsMoving) nav.WalkToRandom();
|
||||
if (_enemy.Nav != null && !_enemy.Nav.IsMoving) _enemy.Nav.WalkToRandom();
|
||||
break;
|
||||
// Pace / Waypoints:P6 实现
|
||||
default:
|
||||
if (!nav.IsMoving) nav.WalkToRandom();
|
||||
|
||||
case PatrolStrategy.Pace: // 撞墙/悬崖翻向的来回踱步(速度驱动,不依赖 nav)
|
||||
var mv = _enemy.Movement;
|
||||
if (mv != null && (mv.IsWallAhead || mv.IsLedgeAhead)) _paceDir = -_paceDir;
|
||||
_enemy.MoveInDirection(_paceDir);
|
||||
break;
|
||||
|
||||
case PatrolStrategy.Waypoints: // 按序(loop 或 ping-pong)巡逻路点
|
||||
if (_waypoints == null || _waypoints.Length == 0)
|
||||
{
|
||||
if (!_warnedNoWaypoints)
|
||||
{
|
||||
Debug.LogWarning("[EnemyLocomotion] PatrolStrategy=Waypoints 但未配置 _waypoints,无法巡逻。", this);
|
||||
_warnedNoWaypoints = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (_enemy.Nav != null && !_enemy.Nav.IsMoving)
|
||||
{
|
||||
AdvanceWaypoint();
|
||||
_enemy.MoveTo(_waypoints[_wpIndex].position);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void AdvanceWaypoint()
|
||||
{
|
||||
if (_pingPong)
|
||||
{
|
||||
int next = _wpIndex + _wpDir;
|
||||
if (next < 0 || next >= _waypoints.Length) { _wpDir = -_wpDir; next = _wpIndex + _wpDir; }
|
||||
_wpIndex = Mathf.Clamp(next, 0, _waypoints.Length - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
_wpIndex = (_wpIndex + 1) % _waypoints.Length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user