test(ai): PerceptionStateMachine locomotion 意图回归测试(绿) 新增 PerceptionStateMachineTests:待机态声明 Idle locomotion 意图、进追逐区 转 Chase 并触发追击能力、Chase 态不再直接声明 locomotion 意图。测试程序集 补 BaseGames.Enemies 引用。断言经真实状态机 + 测试 fake 验证通过。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> @
63 lines
2.4 KiB
C#
63 lines
2.4 KiB
C#
using System.Collections.Generic;
|
|
using NUnit.Framework;
|
|
using BaseGames.AI;
|
|
using BaseGames.Enemies;
|
|
|
|
namespace BaseGames.Tests.EditMode.AI
|
|
{
|
|
/// <summary>
|
|
/// 回归测试:PerceptionStateMachine 的待机/巡逻/警觉声明 locomotion 意图,
|
|
/// 追击走能力(不直接驱动 locomotion)。转换规则见 spec《敌人感知↔状态》。
|
|
/// </summary>
|
|
public class PerceptionStateMachineTests
|
|
{
|
|
static AiGraph Graph()
|
|
{
|
|
var b = new BrainBuilder();
|
|
PerceptionStateMachine.Add(b, new PerceptionStateMachine.Config
|
|
{
|
|
Idle = "Idle", Patrol = "Patrol", Alert = "Alert", Chase = "Chase",
|
|
Death = "Death", Entry = "Idle", Rest = "Patrol",
|
|
IdleMode = LocomotionMode.Idle,
|
|
PatrolMode = LocomotionMode.Patrol,
|
|
AlertMode = LocomotionMode.Face,
|
|
ChaseAbilityId = "chase",
|
|
});
|
|
return b.Build();
|
|
}
|
|
|
|
[Test]
|
|
public void EntryIdleState_SetsIdleLocomotionMode()
|
|
{
|
|
var ctx = new FakeAiContext();
|
|
var rt = new AiRuntime(Graph(), ctx);
|
|
Assert.AreEqual("Idle", rt.CurrentStateName);
|
|
Assert.AreEqual(LocomotionMode.Idle, ctx.L.CurrentMode); // 进入待机即声明 Idle 意图
|
|
}
|
|
|
|
[Test]
|
|
public void InChaseZone_TransitionsToChase_AndTriggersChaseAbility()
|
|
{
|
|
var ctx = new FakeAiContext();
|
|
var rt = new AiRuntime(Graph(), ctx);
|
|
ctx.S.Chase = true; // 进入追逐区
|
|
rt.Tick(0.1f);
|
|
Assert.AreEqual("Chase", rt.CurrentStateName);
|
|
CollectionAssert.Contains(ctx.C.Used, "chase"); // 追击由能力触发
|
|
}
|
|
|
|
[Test]
|
|
public void ChaseState_DoesNotDeclareLocomotionIntent()
|
|
{
|
|
// 追击移动归能力;AI 在 Chase 态不应再声明 SetMode/Approach/Face。
|
|
var ctx = new FakeAiContext();
|
|
var rt = new AiRuntime(Graph(), ctx);
|
|
ctx.S.Chase = true;
|
|
rt.Tick(0.1f); // Idle → Chase(退出 Idle 会调用一次 Stop)
|
|
int lastStop = ctx.L.Calls.FindLastIndex(s => s == "Stop");
|
|
var afterEnteringChase = ctx.L.Calls.GetRange(lastStop + 1, ctx.L.Calls.Count - lastStop - 1);
|
|
CollectionAssert.IsEmpty(afterEnteringChase);
|
|
}
|
|
}
|
|
}
|