From 894ae99984eace587549350ebc341d1c51564f74 Mon Sep 17 00:00:00 2001 From: Joywayer Date: Wed, 29 Jul 2026 12:11:07 +0800 Subject: [PATCH] =?UTF-8?q?test(ai):=20=E8=A1=A5=E6=B5=8B=E7=BB=8F=20AiSta?= =?UTF-8?q?teFragments=20=E7=9A=84=E8=B7=A8=E6=A8=A1=E5=9D=97=E7=8A=B6?= =?UTF-8?q?=E6=80=81=E6=92=9E=E5=90=8D=EF=BC=8CState()=20=E8=A1=A5?= =?UTF-8?q?=E5=BC=95=E5=AF=BC=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../EditMode/AI/AiStateFragmentsTests.cs | 22 +++++++++++++++++++ Assets/_Game/Scripts/AI/BrainBuilder.cs | 4 ++++ 2 files changed, 26 insertions(+) diff --git a/Assets/Tests/EditMode/AI/AiStateFragmentsTests.cs b/Assets/Tests/EditMode/AI/AiStateFragmentsTests.cs index 2dcef846..a5c02489 100644 --- a/Assets/Tests/EditMode/AI/AiStateFragmentsTests.cs +++ b/Assets/Tests/EditMode/AI/AiStateFragmentsTests.cs @@ -114,5 +114,27 @@ namespace BaseGames.Tests.EditMode.AI var b = new BrainBuilder(); Assert.Throws(() => AiStateFragments.AbilityOnce(b, "S", null)); } + + [Test] + public void Fragments_Throw_WhenTwoModulesDeclareSameState() + { + // 守卫存在的真正理由:两个独立模块取了同名状态时, + // 后者的回调会静默覆盖前者。经原语声明必须直接报错。 + var b = new BrainBuilder(); + AiStateFragments.Locomotion(b, "Idle", LocomotionMode.Idle); + var ex = Assert.Throws( + () => AiStateFragments.Locomotion(b, "Idle", LocomotionMode.Patrol)); + StringAssert.Contains("Idle", ex.Message); + } + + [Test] + public void Fragments_Throw_WhenDifferentFragmentKindsCollide() + { + // 跨层撞名同样要挡:未发现层的 Locomotion 态与死亡层的 Ability 态重名。 + var b = new BrainBuilder(); + AiStateFragments.Locomotion(b, "Shared", LocomotionMode.Patrol); + Assert.Throws( + () => AiStateFragments.Ability(b, "Shared", "atk")); + } } } diff --git a/Assets/_Game/Scripts/AI/BrainBuilder.cs b/Assets/_Game/Scripts/AI/BrainBuilder.cs index 860d6e21..948c5e3b 100644 --- a/Assets/_Game/Scripts/AI/BrainBuilder.cs +++ b/Assets/_Game/Scripts/AI/BrainBuilder.cs @@ -16,6 +16,10 @@ namespace BaseGames.AI return this; } + /// + /// 取一个状态,不存在则新建(宽松)。**只用于给别人已声明的态挂转换**。 + /// 要声明一个态的行为(OnEnter/Tick/OnExit)请用 DeclareState()——它会挡住重名覆盖。 + /// public StateBuilder State(string name) { if (!_states.TryGetValue(name, out var s))