feat(enemy): 新增 EnemyLocomotion 执行器(Idle/Patrol-Wander/Face/Approach)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -9,6 +9,7 @@
|
|||||||
"rootNamespace": "BaseGames.Enemies.Navigation",
|
"rootNamespace": "BaseGames.Enemies.Navigation",
|
||||||
"references": [
|
"references": [
|
||||||
"BaseGames.Enemies",
|
"BaseGames.Enemies",
|
||||||
|
"BaseGames.AI",
|
||||||
"PathBerserker2d"
|
"PathBerserker2d"
|
||||||
],
|
],
|
||||||
"autoReferenced": true,
|
"autoReferenced": true,
|
||||||
|
|||||||
@@ -0,0 +1,105 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
using BaseGames.AI;
|
||||||
|
|
||||||
|
namespace BaseGames.Enemies
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 敌人移动执行器:唯一的移动/朝向入口。AI 状态与能力经 IEnemyLocomotion
|
||||||
|
/// 声明意图,本组件每帧把当前模式翻译为对 EnemyBase/IPathAgent 的调用。
|
||||||
|
/// 取代散落的 MoveTo/StopMovement/FacePlayer/FaceTarget 直调与三个协程能力。
|
||||||
|
/// </summary>
|
||||||
|
[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<EnemyBase>();
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 9201463979893884288d3645a607eb90
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
Reference in New Issue
Block a user