using System;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
namespace BaseGames.AI
{
///
/// 反射收集所有 [AiDefinition] 的 AiScript 子类,按 id 提供共享 AiGraph(flyweight)。
/// 同一 id 全实例共享同一 AiScript 实例 → 同一张不可变 AiGraph。
///
public static class AiDefinitionRegistry
{
static Dictionary _byId;
// 项目已关闭 Domain Reload:静态缓存需在进入播放时重置,保证按最新类型重建。
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
static void ResetOnPlay() => _byId = null;
static void EnsureBuilt()
{
if (_byId != null) return;
_byId = new Dictionary();
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
{
Type[] types;
try { types = asm.GetTypes(); }
catch (ReflectionTypeLoadException e) { types = e.Types; }
if (types == null) continue;
for (int i = 0; i < types.Length; i++)
{
var t = types[i];
if (t == null || t.IsAbstract || !typeof(AiScript).IsAssignableFrom(t)) continue;
var attr = t.GetCustomAttribute();
if (attr == null) continue;
if (_byId.ContainsKey(attr.Id))
throw new InvalidOperationException(
$"AiDefinitionRegistry: 重复的 AI 定义 id '{attr.Id}'({t.FullName})。");
_byId[attr.Id] = (AiScript)Activator.CreateInstance(t);
}
}
}
public static bool Has(string id)
{
EnsureBuilt();
return _byId.ContainsKey(id);
}
/// 取 id 对应的共享 AiGraph;不存在则显式抛错(根因暴露,不做兜底)。
public static AiGraph GetGraph(string id) => GetDefinition(id).GetOrBuildGraph();
/// 取 id 对应的定义;不存在则显式抛错(根因暴露,不做兜底)。
public static IAiDefinition GetDefinition(string id)
{
EnsureBuilt();
if (!_byId.TryGetValue(id, out var script))
throw new InvalidOperationException(
$"AiDefinitionRegistry: 未找到 AI 定义 id '{id}'。请确认存在 [AiDefinition(\"{id}\")] 的 AiScript 子类。");
return script;
}
public static IEnumerable Ids
{
get { EnsureBuilt(); return _byId.Keys; }
}
}
}