feat(ai): BrainBuilder.DeclareState——重复声明状态即报错,防模块间同名静默覆盖

State() 仍保持宽松(有则取),用于给已声明的态挂边;DeclareState() 只用于
首次声明行为,重复声明同名状态会抛异常。AiStateFragments 的四个建态原语
(Locomotion/Ability/AbilityOnce/Terminal)改用 DeclareState。同时给
IEngagementModule/IDeathModule/IUnawareModule 补充不变量说明。
This commit is contained in:
2026-07-29 12:01:19 +08:00
parent 5dcbce6019
commit 80fdc36762
6 changed files with 56 additions and 5 deletions
@@ -85,5 +85,34 @@ namespace BaseGames.Tests.EditMode.AI
b.State("Real");
Assert.DoesNotThrow(() => b.RequireState("Real"));
}
[Test]
public void DeclareState_Throws_OnDuplicateName()
{
var b = new BrainBuilder();
b.DeclareState("Dup");
var ex = Assert.Throws<System.InvalidOperationException>(() => b.DeclareState("Dup"));
StringAssert.Contains("Dup", ex.Message);
}
[Test]
public void DeclareState_ReturnsUsableBuilder_OnFirstDeclare()
{
var b = new BrainBuilder();
b.Entry("A");
b.DeclareState("A").To("B").When(c => true, "go");
b.DeclareState("B");
Assert.DoesNotThrow(() => b.Build());
}
[Test]
public void State_StaysLenient_ForAttachingToDeclaredState()
{
// State() 仍是"有则取"——骨架要给模块已声明的态挂升级边,靠的就是这个。
var b = new BrainBuilder();
b.Entry("A");
b.DeclareState("A");
Assert.DoesNotThrow(() => b.State("A").To("A").When(c => false, "noop"));
}
}
}