TH1/Unity/Assets/Scripts/TH1_Logic/AI/Kernel/BehaviourTreeAIKernel.cs
2026-06-29 11:07:07 +08:00

115 lines
3.8 KiB
C#

using System.Collections.Generic;
using Logic.CrashSight;
using NodeCanvas.BehaviourTrees;
using NodeCanvas.Framework;
using RuntimeData;
using TH1_Logic.Core;
using UnityEngine;
namespace Logic.AI
{
public sealed class BehaviourTreeAIKernel : IAIKernel
{
private AILogicContext _context;
private BehaviourTreeOwner _btOwner;
private readonly List<List<uint>> _nodeRecords = new();
public AIKernelType KernelType => AIKernelType.BehaviourTree;
public void Initialize(AILogicContext context)
{
_context = context;
var logicObject = GameObject.Find("AIBT");
if (logicObject == null)
{
LogSystem.LogError("AIBT object missing, BehaviourTreeAIKernel can not run.");
return;
}
_btOwner = logicObject.GetComponent<BehaviourTreeOwner>();
if (_btOwner == null)
{
LogSystem.LogError("AIBT BehaviourTreeOwner missing, BehaviourTreeAIKernel can not run.");
return;
}
var dataVariable = _btOwner.blackboard.GetVariable<AICalculatorData>("Data");
if (dataVariable == null)
{
LogSystem.LogError("AIBT blackboard variable Data missing, BehaviourTreeAIKernel can not run.");
_btOwner = null;
return;
}
if (dataVariable.value == null)
{
dataVariable.value = _context.Data;
}
else
{
_context.Data = dataVariable.value;
}
}
public void StartTurn(MapData mapData, PlayerData playerData)
{
if (_context == null || _btOwner == null) return;
_context.Generator.Init(mapData, playerData);
_context.Data.AiDiffInfo = _context.Config.GetAIDiffInfo(mapData.MapConfig.AIDiff);
_context.Data.Refresh(mapData, playerData);
_btOwner.StopBehaviour();
_btOwner.StartBehaviour();
MainEditor.Instance.Data = _context.Data;
}
public AIKernelUpdate Update()
{
if (_context == null || _btOwner == null) return AIKernelUpdate.Finished;
var index = 0;
for (var i = 0; i < _nodeRecords.Count; i++) _nodeRecords[i].Clear();
var nodeRecordsUsed = 0;
while (true)
{
if (MainEditor.Instance.IsEditor && !MainEditor.Instance.IsGo) return AIKernelUpdate.None;
index++;
if (index > nodeRecordsUsed)
{
nodeRecordsUsed = index;
if (index > _nodeRecords.Count) _nodeRecords.Add(new List<uint>());
}
_context.Data.ClearCache();
_nodeRecords[index - 1].Add(MainEditor.Instance.BTNodeId);
_btOwner.UpdateBehaviour();
MainEditor.Instance.IsGo = false;
_nodeRecords[index - 1].Add(MainEditor.Instance.BTNodeId);
if (_context.Data.MaxAiAction != null || _context.Data.IsFinish) break;
if (index > 150)
{
LogSystem.LogError($"AI 行为树疑似死循环,最终记录点为:{MainEditor.Instance.BTNodeId}");
return AIKernelUpdate.Finished;
}
}
if (_context.Data.MaxAiAction == null || index > 100) return AIKernelUpdate.Finished;
var action = _context.Data.MaxAiAction;
_context.Data.MaxAiAction = null;
return AIKernelUpdate.ActionReady(action);
}
public void FinishTurn()
{
if (_btOwner != null) _btOwner.StopBehaviour();
if (_context?.Data != null) _context.Data.MaxAiAction = null;
}
}
}