diff --git a/Assets/Tests/EditMode/AI/AiRuntimeTests.cs b/Assets/Tests/EditMode/AI/AiRuntimeTests.cs index 0a4a2aa1..1842699c 100644 --- a/Assets/Tests/EditMode/AI/AiRuntimeTests.cs +++ b/Assets/Tests/EditMode/AI/AiRuntimeTests.cs @@ -11,12 +11,12 @@ namespace BaseGames.Tests.EditMode.AI b.Entry("Patrol"); b.Global().To("Dead").OnEvent(AiSignal.Died); b.State("Patrol") - .Tick(c => c.Mover.WalkRandom()) + .Tick(c => c.Locomotion.SetMode(LocomotionMode.Patrol)) .To("Chase").When(c => c.Sensor.SeesPlayer(), "SeesPlayer"); b.State("Chase") - .OnEnter(c => c.Mover.FacePlayer()) - .OnExit(c => c.Mover.Stop()) - .Tick(c => c.Mover.MoveTo(c.Sensor.LastKnown)) + .OnEnter(c => c.Locomotion.Face(c.Sensor.LastKnown)) + .OnExit(c => c.Locomotion.Stop()) + .Tick(c => c.Locomotion.MoveTo(c.Sensor.LastKnown)) .To("Search").When(c => c.Sensor.LostFor(2f), "LostFor(2s)"); b.State("Search") .To("Patrol").After(3f); @@ -37,7 +37,7 @@ namespace BaseGames.Tests.EditMode.AI var ctx = new FakeAiContext(); var rt = new AiRuntime(Graph(), ctx); rt.Tick(0.1f); - CollectionAssert.Contains(ctx.M.Calls, "WalkRandom"); + CollectionAssert.Contains(ctx.L.Calls, "SetMode:Patrol"); } [Test] @@ -48,7 +48,7 @@ namespace BaseGames.Tests.EditMode.AI ctx.S.Sees = true; rt.Tick(0.1f); Assert.AreEqual("Chase", rt.CurrentStateName); - CollectionAssert.Contains(ctx.M.Calls, "FacePlayer"); // Chase.OnEnter + CollectionAssert.Contains(ctx.L.Calls, "Face"); // Chase.OnEnter } [Test] @@ -61,7 +61,7 @@ namespace BaseGames.Tests.EditMode.AI rt.Tick(0.1f); Assert.AreEqual("Patrol", rt.CurrentStateName); // 未转换 Assert.IsTrue(rt.IsSuspended); - CollectionAssert.DoesNotContain(ctx.M.Calls, "WalkRandom"); // Tick 也不跑 + CollectionAssert.DoesNotContain(ctx.L.Calls, "SetMode:Patrol"); // Tick 也不跑 } [Test] @@ -98,7 +98,7 @@ namespace BaseGames.Tests.EditMode.AI var rt = new AiRuntime(Graph(), ctx); ctx.S.Sees = true; rt.Tick(0.1f); // Patrol -> Chase ctx.S.Sees = false; ctx.S.LostForValue = 5f; rt.Tick(0.1f);// Chase -> Search (触发 Chase.OnExit) - CollectionAssert.Contains(ctx.M.Calls, "Stop"); + CollectionAssert.Contains(ctx.L.Calls, "Stop"); } [Test] @@ -106,10 +106,10 @@ namespace BaseGames.Tests.EditMode.AI { var b = new BrainBuilder(); b.Entry("Start"); - b.State("Start").OnEnter(c => c.Mover.LookAround()); + b.State("Start").OnEnter(c => c.Locomotion.SetMode(LocomotionMode.Idle)); var ctx = new FakeAiContext(); var rt = new AiRuntime(b.Build(), ctx); - CollectionAssert.Contains(ctx.M.Calls, "LookAround"); + CollectionAssert.Contains(ctx.L.Calls, "SetMode:Idle"); } [Test] diff --git a/Assets/Tests/EditMode/AI/Fakes/FakeAiContext.cs b/Assets/Tests/EditMode/AI/Fakes/FakeAiContext.cs index f12d1c71..4f508d3c 100644 --- a/Assets/Tests/EditMode/AI/Fakes/FakeAiContext.cs +++ b/Assets/Tests/EditMode/AI/Fakes/FakeAiContext.cs @@ -16,18 +16,6 @@ namespace BaseGames.Tests.EditMode.AI public Vector2 LastKnown => Last; } - public sealed class FakeMover : IMover - { - public List Calls = new List(); - public void MoveTo(Vector2 t) => Calls.Add("MoveTo"); - public void FacePlayer() => Calls.Add("FacePlayer"); - public void Stop() => Calls.Add("Stop"); - public void WalkRandom() => Calls.Add("WalkRandom"); - public void LookAround() => Calls.Add("LookAround"); - public void UseChaseSpeed() => Calls.Add("UseChaseSpeed"); - public void UsePatrolSpeed() => Calls.Add("UsePatrolSpeed"); - } - public sealed class FakeCombat : ICombatant { public string Running; public List Used = new List(); @@ -50,12 +38,12 @@ namespace BaseGames.Tests.EditMode.AI public sealed class FakeAiContext : IAiContext { public FakeSensor S = new FakeSensor(); - public FakeMover M = new FakeMover(); + public FakeLocomotion L = new FakeLocomotion(); public FakeCombat C = new FakeCombat(); public FakeVitals V = new FakeVitals(); public Blackboard BB = new Blackboard(); public ISensor Sensor => S; - public IMover Mover => M; + public IEnemyLocomotion Locomotion => L; public ICombatant Combat => C; public IActorVitals Vitals => V; public Blackboard Blackboard => BB; diff --git a/Assets/Tests/EditMode/AI/Fakes/FakeLocomotion.cs b/Assets/Tests/EditMode/AI/Fakes/FakeLocomotion.cs new file mode 100644 index 00000000..1bd8e57e --- /dev/null +++ b/Assets/Tests/EditMode/AI/Fakes/FakeLocomotion.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; +using UnityEngine; +using BaseGames.AI; + +namespace BaseGames.Tests.EditMode.AI +{ + public sealed class FakeLocomotion : IEnemyLocomotion + { + public List Calls = new List(); + public LocomotionMode CurrentMode { get; private set; } + public bool IsMoving { get; set; } + public void SetMode(LocomotionMode mode) { CurrentMode = mode; Calls.Add("SetMode:" + mode); } + public void Approach(Transform t) { CurrentMode = LocomotionMode.Approach; Calls.Add("Approach"); } + public void MoveTo(Vector2 p) { Calls.Add("MoveTo"); } + public void Face(Vector2 p) { CurrentMode = LocomotionMode.Face; Calls.Add("Face"); } + public void Stop() { CurrentMode = LocomotionMode.Idle; Calls.Add("Stop"); } + } +} diff --git a/Assets/_Game/Scripts/AI/IMover.cs.meta b/Assets/Tests/EditMode/AI/Fakes/FakeLocomotion.cs.meta similarity index 83% rename from Assets/_Game/Scripts/AI/IMover.cs.meta rename to Assets/Tests/EditMode/AI/Fakes/FakeLocomotion.cs.meta index 9d6f4070..f27d188e 100644 --- a/Assets/_Game/Scripts/AI/IMover.cs.meta +++ b/Assets/Tests/EditMode/AI/Fakes/FakeLocomotion.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: bfa62d8e02c8fa644b4c18929b82cbcb +guid: 9f61c34c953e8534fa53898c69cd4de0 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Assets/_Game/Scripts/AI/IAiContext.cs b/Assets/_Game/Scripts/AI/IAiContext.cs index b96040fc..308c544e 100644 --- a/Assets/_Game/Scripts/AI/IAiContext.cs +++ b/Assets/_Game/Scripts/AI/IAiContext.cs @@ -7,7 +7,7 @@ namespace BaseGames.AI public interface IAiContext { ISensor Sensor { get; } - IMover Mover { get; } + IEnemyLocomotion Locomotion { get; } ICombatant Combat { get; } IActorVitals Vitals { get; } Blackboard Blackboard { get; } diff --git a/Assets/_Game/Scripts/AI/IMover.cs b/Assets/_Game/Scripts/AI/IMover.cs deleted file mode 100644 index 6c3b587b..00000000 --- a/Assets/_Game/Scripts/AI/IMover.cs +++ /dev/null @@ -1,16 +0,0 @@ -using UnityEngine; - -namespace BaseGames.AI -{ - /// 移动能力接口(第 3 阶段由 MoverAdapter 适配移动系统)。 - public interface IMover - { - void MoveTo(Vector2 target); - void FacePlayer(); - void Stop(); - void WalkRandom(); - void LookAround(); - void UseChaseSpeed(); // 切到追击速度(适配器内部读配置的 RunSpeed) - void UsePatrolSpeed(); // 切到巡逻速度(适配器内部读配置的 WalkSpeed) - } -} diff --git a/Assets/_Game/Scripts/Enemies/AIBrain/EnemyBrainContext.cs b/Assets/_Game/Scripts/Enemies/AIBrain/EnemyBrainContext.cs index 32a64ac7..50ea5111 100644 --- a/Assets/_Game/Scripts/Enemies/AIBrain/EnemyBrainContext.cs +++ b/Assets/_Game/Scripts/Enemies/AIBrain/EnemyBrainContext.cs @@ -7,7 +7,7 @@ namespace BaseGames.Enemies /// 把 EnemyBase 的子系统包装成 BrainGraph 的能力接口(每敌人一实例)。 /// 状态逻辑只依赖这些接口,不直接引用具体子系统。 /// - public sealed class EnemyBrainContext : IAiContext, ISensor, IMover, ICombatant, IActorVitals, IEnemyActor + public sealed class EnemyBrainContext : IAiContext, ISensor, ICombatant, IActorVitals, IEnemyActor { readonly EnemyBase _enemy; readonly Blackboard _blackboard = new Blackboard(); @@ -18,7 +18,7 @@ namespace BaseGames.Enemies // ---- IAiContext ---- public ISensor Sensor => this; - public IMover Mover => this; + public IEnemyLocomotion Locomotion => _enemy.Locomotion; public ICombatant Combat => this; public IActorVitals Vitals => this; public Blackboard Blackboard => _blackboard; @@ -53,19 +53,6 @@ namespace BaseGames.Enemies public bool LostFor(float seconds) => !InVisionZone() && _lostTimer >= seconds; public Vector2 LastKnown => _lastKnown; - // ---- IMover ---- - public void MoveTo(Vector2 target) => _enemy.MoveTo(target); - public void FacePlayer() => _enemy.FacePlayer(); - public void Stop() => _enemy.StopMovement(); - public void WalkRandom() - { - var nav = _enemy.Nav; - if (nav != null && !nav.IsMoving) nav.WalkToRandom(); - } - public void LookAround() => _enemy.BeginLookAround(); - public void UseChaseSpeed() => _enemy.Nav?.SetSpeed(_enemy.Stats != null ? _enemy.Stats.RunSpeed : 0f); - public void UsePatrolSpeed() => _enemy.Nav?.SetSpeed(_enemy.Stats != null ? _enemy.Stats.WalkSpeed : 0f); - // ---- ICombatant ---- public bool UseAbility(string abilityId) {