feat(ai): EnemyAiBrain 组件——承载 AiRuntime、逐帧推进、池复用重置、信号入口

This commit is contained in:
2026-07-03 15:00:59 +08:00
parent 20c2568222
commit 4994360927
2 changed files with 70 additions and 0 deletions
@@ -0,0 +1,59 @@
using UnityEngine;
using BaseGames.AI;
namespace BaseGames.Enemies
{
/// <summary>
/// 把 BrainGraph 决策层挂到敌人上:按 id 取共享 AiGraph、构造 AiRuntime、逐帧推进。
/// 取代旧的行为树组件。
/// </summary>
[DisallowMultipleComponent]
[RequireComponent(typeof(EnemyBase))]
public sealed class EnemyAiBrain : MonoBehaviour
{
[Tooltip("对应 [AiDefinition(id)] AI id E001")]
[SerializeField] string _definitionId;
EnemyBase _enemy;
EnemyBrainContext _context;
AiRuntime _runtime;
public string DefinitionId => _definitionId;
public string CurrentStateName => _runtime != null ? _runtime.CurrentStateName : "(none)";
public bool IsSuspended => _runtime != null && _runtime.IsSuspended;
public AiRuntime Runtime => _runtime;
void Awake()
{
_enemy = GetComponent<EnemyBase>();
if (string.IsNullOrEmpty(_definitionId))
{
// 根因暴露:漏配 id 直接报错,不静默兜底。
Debug.LogError($"EnemyAiBrain 未配置 _definitionId{name}", this);
enabled = false;
return;
}
var graph = AiDefinitionRegistry.GetGraph(_definitionId); // 不存在则抛异常
_context = new EnemyBrainContext(_enemy);
_runtime = new AiRuntime(graph, _context);
}
void Update()
{
if (_runtime == null) return;
float dt = Time.deltaTime;
_context.Refresh(dt);
_runtime.Tick(dt);
}
/// <summary>对象池复用时由 EnemyBase.OnSpawn 调用:回到 Entry、清临时态。</summary>
public void ResetBrain()
{
_context?.ResetScratch();
_runtime?.Reset();
}
/// <summary>信号入口,供 EnemyBase 转发死亡等事件到决策层。</summary>
public void Send(AiSignal signal) => _runtime?.Send(signal);
}
}