using NUnit.Framework; using BaseGames.AI; using BaseGames.Enemies; namespace BaseGames.Tests.EditMode.AI { public class UnawareModuleTests { // 只跑未发现层自身(不挂骨架升级边),验证态、行为与内部边。 static AiRuntime RunAlone(IUnawareModule m, FakeAiContext ctx) { var b = new BrainBuilder(); m.Declare(b); m.Link(b); b.Entry(m.Entry); return new AiRuntime(b.Build(), ctx); } [Test] public void SinglePost_OneState_EntryEqualsRest() { var m = new SinglePost(LocomotionMode.Patrol); Assert.AreEqual(1, m.States.Count); Assert.AreEqual(m.Entry, m.Rest); var ctx = new FakeAiContext(); RunAlone(m, ctx); Assert.AreEqual(LocomotionMode.Patrol, ctx.L.CurrentMode); } [Test] public void DisguiseThenPatrol_EntryIsDisguise_RestIsPatrol() { var m = new DisguiseThenPatrol(); Assert.AreEqual(DisguiseThenPatrol.Disguise, m.Entry); Assert.AreEqual(DisguiseThenPatrol.Patrol, m.Rest); CollectionAssert.AreEquivalent( new[] { DisguiseThenPatrol.Disguise, DisguiseThenPatrol.Patrol }, m.States); } [Test] public void DisguiseThenPatrol_LinkAddsNoEdges_DisguiseStaysPut() { var ctx = new FakeAiContext(); var rt = RunAlone(new DisguiseThenPatrol(), ctx); Assert.AreEqual(DisguiseThenPatrol.Disguise, rt.CurrentStateName); for (int i = 0; i < 20; i++) rt.Tick(1f); // 无内部边:伪装态自己不会跑掉,只能被骨架的升级边带走 Assert.AreEqual(DisguiseThenPatrol.Disguise, rt.CurrentStateName); Assert.AreEqual(LocomotionMode.Idle, ctx.L.CurrentMode); } [Test] public void AlternatingIdlePatrol_SwitchesOnDwellTimers() { var m = new AlternatingIdlePatrol(idleDwell: 2f, patrolDwell: 3f); var ctx = new FakeAiContext(); var rt = RunAlone(m, ctx); Assert.AreEqual(AlternatingIdlePatrol.Idle, rt.CurrentStateName); rt.Tick(1f); Assert.AreEqual(AlternatingIdlePatrol.Idle, rt.CurrentStateName); // 未到 2s rt.Tick(1.5f); Assert.AreEqual(AlternatingIdlePatrol.Patrol, rt.CurrentStateName); // 累计 2.5s ≥ 2s Assert.AreEqual(LocomotionMode.Patrol, ctx.L.CurrentMode); rt.Tick(3.5f); Assert.AreEqual(AlternatingIdlePatrol.Idle, rt.CurrentStateName); // ≥ 3s 回站立 } } }