feat(enemy): PerceptionStateMachine 增加 ApproachAttack 风格(寻路逼近↔选招攻击)+测试
This commit is contained in:
@@ -275,6 +275,88 @@ namespace BaseGames.Tests.EditMode.AI
|
||||
Assert.AreEqual(LocomotionMode.Patrol, ctx.L.CurrentMode); // 落地即巡逻移动意图
|
||||
}
|
||||
|
||||
// ── ApproachAttack 交战风格 ───────────────────────────────────────
|
||||
static AiGraph GraphApproach(string entry = "Idle")
|
||||
{
|
||||
var b = new BrainBuilder();
|
||||
PerceptionStateMachine.Add(b, new PerceptionStateMachine.Config
|
||||
{
|
||||
Idle = "Idle", Patrol = "Patrol", Alert = "Alert", Death = "Death",
|
||||
Entry = entry, Rest = "Patrol",
|
||||
IdleMode = LocomotionMode.Idle, PatrolMode = LocomotionMode.Patrol, AlertMode = LocomotionMode.Face,
|
||||
Engagement = PerceptionStateMachine.EngagementStyle.ApproachAttack,
|
||||
ApproachState = "Approach", AttackState = "Attack",
|
||||
});
|
||||
return b.Build();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Approach_EnteredFromChaseZone_UsesPursue()
|
||||
{
|
||||
var ctx = new Ctx();
|
||||
var rt = new AiRuntime(GraphApproach(), ctx);
|
||||
ctx.S.Chase = true;
|
||||
rt.Tick(0.1f);
|
||||
Assert.AreEqual("Approach", rt.CurrentStateName);
|
||||
CollectionAssert.Contains(ctx.L.Calls, "Pursue");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Approach_ToAttack_WhenEligibleAttack()
|
||||
{
|
||||
var ctx = new Ctx();
|
||||
var rt = new AiRuntime(GraphApproach(), ctx);
|
||||
ctx.S.Chase = true; rt.Tick(0.1f);
|
||||
ctx.C.Eligible = true;
|
||||
rt.Tick(0.1f);
|
||||
Assert.AreEqual("Attack", rt.CurrentStateName);
|
||||
CollectionAssert.Contains(ctx.C.Used, "best");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Attack_StopsLocomotion_OnEnter()
|
||||
{
|
||||
var ctx = new Ctx();
|
||||
var rt = new AiRuntime(GraphApproach(), ctx);
|
||||
ctx.S.Chase = true; rt.Tick(0.1f);
|
||||
ctx.C.Eligible = true; rt.Tick(0.1f);
|
||||
CollectionAssert.Contains(ctx.L.Calls, "Stop");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Attack_ToApproach_WhenAttackDone()
|
||||
{
|
||||
var ctx = new Ctx();
|
||||
var rt = new AiRuntime(GraphApproach(), ctx);
|
||||
ctx.S.Chase = true; rt.Tick(0.1f);
|
||||
ctx.C.Eligible = true; rt.Tick(0.1f);
|
||||
Assert.AreEqual("Attack", rt.CurrentStateName);
|
||||
ctx.C.Running = null;
|
||||
rt.Tick(0.1f);
|
||||
Assert.AreEqual("Approach", rt.CurrentStateName);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Approach_ToRest_WhenLeftAllZones()
|
||||
{
|
||||
var ctx = new Ctx();
|
||||
var rt = new AiRuntime(GraphApproach(), ctx);
|
||||
ctx.S.Chase = true; rt.Tick(0.1f);
|
||||
ctx.S.Chase = false; ctx.S.Vision = false;
|
||||
rt.Tick(0.1f);
|
||||
Assert.AreEqual("Patrol", rt.CurrentStateName);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ApproachAttack_Death_IsGlobal()
|
||||
{
|
||||
var ctx = new Ctx();
|
||||
var rt = new AiRuntime(GraphApproach(), ctx);
|
||||
ctx.S.Chase = true; rt.Tick(0.1f);
|
||||
rt.Send(AiSignal.Died); rt.Tick(0.1f);
|
||||
Assert.AreEqual("Death", rt.CurrentStateName);
|
||||
}
|
||||
|
||||
// ── 死亡(全局事件,任意态可达)───────────────────────────────────
|
||||
|
||||
[Test]
|
||||
|
||||
Reference in New Issue
Block a user