diff --git a/Assets/_Game/Scripts/AI/AiRecipeSO.cs b/Assets/_Game/Scripts/AI/AiRecipeSO.cs
new file mode 100644
index 00000000..935211f0
--- /dev/null
+++ b/Assets/_Game/Scripts/AI/AiRecipeSO.cs
@@ -0,0 +1,36 @@
+using UnityEngine;
+using BaseGames.Core.Events;
+
+namespace BaseGames.AI
+{
+ ///
+ /// AI 配方资产基类。子类以序列化字段描述一张图,Build 里组装。
+ /// 一个资产 = 一种敌人 AI;所有引用该资产的实例共享同一张 AiGraph(flyweight)。
+ ///
+ public abstract class AiRecipeSO : ScriptableObject, IAiDefinition
+ {
+ AiGraph _cached;
+
+ void OnEnable()
+ {
+ // 项目已关闭 Domain Reload:SO 的运行时态在多次 Play 会话间会残留,
+ // 改了配方再进 Play 仍用旧图。登记到统一的"进入 Play 前重置"通道。
+ PlayModeResetHook.Register(ClearCache);
+ }
+
+ void ClearCache() => _cached = null;
+
+ public AiGraph GetOrBuildGraph()
+ {
+ if (_cached == null)
+ {
+ var b = new BrainBuilder();
+ Build(b);
+ _cached = b.Build();
+ }
+ return _cached;
+ }
+
+ protected abstract void Build(BrainBuilder b);
+ }
+}
diff --git a/Assets/_Game/Scripts/AI/AiRecipeSO.cs.meta b/Assets/_Game/Scripts/AI/AiRecipeSO.cs.meta
new file mode 100644
index 00000000..88bc0068
--- /dev/null
+++ b/Assets/_Game/Scripts/AI/AiRecipeSO.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 3b4ea7eede5a322448cfccec3eff2acf
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/_Game/Scripts/AI/AiScript.cs b/Assets/_Game/Scripts/AI/AiScript.cs
index e5632de8..22fe173a 100644
--- a/Assets/_Game/Scripts/AI/AiScript.cs
+++ b/Assets/_Game/Scripts/AI/AiScript.cs
@@ -14,7 +14,7 @@ namespace BaseGames.AI
/// 一种敌人 AI 的声明基类(唯一事实来源)。子类实现 Build 用 fluent 描述状态机。
/// 构建结果 AiGraph 每类型只建一次、实例共享(flyweight)。
///
- public abstract class AiScript
+ public abstract class AiScript : IAiDefinition
{
AiGraph _cached;
diff --git a/Assets/_Game/Scripts/AI/BaseGames.AI.asmdef b/Assets/_Game/Scripts/AI/BaseGames.AI.asmdef
index 2115deb7..30e9e706 100644
--- a/Assets/_Game/Scripts/AI/BaseGames.AI.asmdef
+++ b/Assets/_Game/Scripts/AI/BaseGames.AI.asmdef
@@ -2,7 +2,8 @@
"name": "BaseGames.AI",
"rootNamespace": "BaseGames.AI",
"references": [
- "BaseGames.Core"
+ "BaseGames.Core",
+ "BaseGames.Core.Events"
],
"includePlatforms": [],
"excludePlatforms": [],
diff --git a/Assets/_Game/Scripts/AI/IAiDefinition.cs b/Assets/_Game/Scripts/AI/IAiDefinition.cs
new file mode 100644
index 00000000..53892a4d
--- /dev/null
+++ b/Assets/_Game/Scripts/AI/IAiDefinition.cs
@@ -0,0 +1,12 @@
+namespace BaseGames.AI
+{
+ ///
+ /// 能产出共享 AiGraph 的东西。两个实现:
+ /// AiScript(定制路径,写 C# 类)与 AiRecipeSO(配方路径,建资产)。
+ ///
+ public interface IAiDefinition
+ {
+ /// 惰性构建并缓存共享图(flyweight:每个定义只建一次)。
+ AiGraph GetOrBuildGraph();
+ }
+}
diff --git a/Assets/_Game/Scripts/AI/IAiDefinition.cs.meta b/Assets/_Game/Scripts/AI/IAiDefinition.cs.meta
new file mode 100644
index 00000000..d680a12a
--- /dev/null
+++ b/Assets/_Game/Scripts/AI/IAiDefinition.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: bdf86cde06fe7b8468b243b2bca11d22
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant: