115 lines
3.8 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|