using NUnit.Framework; using BaseGames.AI; using BaseGames.Enemies; namespace BaseGames.Tests.EditMode.AI { public class ApproachAttackEngagementTests { const string Rest = "Rest"; static AiRuntime RunAlone(FakeAiContext ctx) { var m = new ApproachAttackEngagement(); var b = new BrainBuilder(); AiStateFragments.Locomotion(b, Rest, LocomotionMode.Patrol); m.Build(b, Rest); b.Entry(m.EntryState); return new AiRuntime(b.Build(), ctx); } [Test] public void Approach_PursuesLastKnown() { var ctx = new FakeAiContext(); ctx.S.Chase = true; ctx.S.Last = new UnityEngine.Vector2(5f, 1f); RunAlone(ctx); Assert.AreEqual(new UnityEngine.Vector2(5f, 1f), ctx.L.PursuedTo); } [Test] public void Approach_ToAttack_WhenEligibleAttackExists() { var ctx = new FakeAiContext(); ctx.S.Chase = true; var rt = RunAlone(ctx); Assert.AreEqual(ApproachAttackEngagement.Approach, rt.CurrentStateName); ctx.C.Eligible = true; rt.Tick(0.1f); Assert.AreEqual(ApproachAttackEngagement.Attack, rt.CurrentStateName); CollectionAssert.Contains(ctx.C.Used, "best"); } [Test] public void Attack_BackToApproach_WhenAbilityDone() { var ctx = new FakeAiContext(); ctx.S.Chase = true; ctx.C.Eligible = true; var rt = RunAlone(ctx); rt.Tick(0.1f); Assert.AreEqual(ApproachAttackEngagement.Attack, rt.CurrentStateName); ctx.C.Running = null; // 招式打完 rt.Tick(0.1f); Assert.AreEqual(ApproachAttackEngagement.Approach, rt.CurrentStateName); } [Test] public void Approach_ExitsToRest_WhenAllZonesLost() { var ctx = new FakeAiContext(); ctx.S.Chase = true; var rt = RunAlone(ctx); ctx.S.Chase = false; ctx.S.Vision = false; rt.Tick(0.1f); Assert.AreEqual(Rest, rt.CurrentStateName); } // 有意的行为变更:攻击起手后打完,不中途收招 [Test] public void Attack_CompletesEvenWhenPlayerLeavesAllZones() { var ctx = new FakeAiContext(); ctx.S.Chase = true; ctx.C.Eligible = true; var rt = RunAlone(ctx); rt.Tick(0.1f); Assert.AreEqual(ApproachAttackEngagement.Attack, rt.CurrentStateName); ctx.S.Chase = false; ctx.S.Vision = false; // 前摇中玩家跑掉 rt.Tick(0.1f); Assert.AreEqual(ApproachAttackEngagement.Attack, rt.CurrentStateName); // 不中途收招 ctx.C.Running = null; // 招式打完 rt.Tick(0.1f); Assert.AreEqual(ApproachAttackEngagement.Approach, rt.CurrentStateName); rt.Tick(0.1f); Assert.AreEqual(Rest, rt.CurrentStateName); // 再经 Approach 自然脱战 } } }