diff --git a/Assets/Tests/EditMode/AI/BrainBuilderTests.cs b/Assets/Tests/EditMode/AI/BrainBuilderTests.cs index aa68f2da..e3265891 100644 --- a/Assets/Tests/EditMode/AI/BrainBuilderTests.cs +++ b/Assets/Tests/EditMode/AI/BrainBuilderTests.cs @@ -69,5 +69,21 @@ namespace BaseGames.Tests.EditMode.AI b.State("A").To("Nonexistent").When(c => true); Assert.Throws(() => b.Build()); } + + [Test] + public void RequireState_Throws_WhenStateNotDeclared() + { + var b = new BrainBuilder(); + var ex = Assert.Throws(() => b.RequireState("Ghost")); + StringAssert.Contains("Ghost", ex.Message); + } + + [Test] + public void RequireState_Passes_WhenStateDeclared() + { + var b = new BrainBuilder(); + b.State("Real"); + Assert.DoesNotThrow(() => b.RequireState("Real")); + } } } diff --git a/Assets/_Game/Scripts/AI/BrainBuilder.cs b/Assets/_Game/Scripts/AI/BrainBuilder.cs index fe64a4e6..fe0a7aea 100644 --- a/Assets/_Game/Scripts/AI/BrainBuilder.cs +++ b/Assets/_Game/Scripts/AI/BrainBuilder.cs @@ -28,6 +28,17 @@ namespace BaseGames.AI public GlobalBuilder Global() => new GlobalBuilder(this); + /// + /// 要求状态已被声明(含行为回调)。模块给"别人声明的态"挂边前调用。 + /// 未声明即抛——否则 State() 会静默新建一个空态,敌人杵着不动且无任何报错。 + /// + public void RequireState(string name) + { + if (!_states.ContainsKey(name)) + throw new InvalidOperationException( + $"BrainBuilder: 状态 '{name}' 尚未声明。请先声明它的行为(AiStateFragments.* 或 State(name)),再挂转换。"); + } + internal void AddGlobal(Transition t) => _globals.Add(t); public AiGraph Build()