//============= Copyright (c) Ludic GmbH, All rights reserved. ============== // // Purpose: Part of the My Behaviour Tree Code // //============================================================================= using System.Collections; using System.Collections.Generic; using System.Xml.Serialization; using UnityEngine; namespace MyBT { [XmlInclude(typeof(DecoratorNode))] public class TreeNode : Node { // the "parent" run tree node, must be null in root treenode [SerializeField] public string treeNodeName; public void Init(int _nodeDepth, Token[] _tokens, string _name) { base.Init(_nodeDepth, _tokens); treeNodeName = _name; } public override IEnumerable Tick(NodeRuntimeData parentNodeRuntimeData, int recursions) { if (debugInternalActive) { Debug.Log(NodeLogger($"Tick", $"")); } // only work with 1 child && failsave in case we have an infinite loop if ((children.Count == 1) && (recursions < recursionLimit)) { using (NodeRuntimeData myNodeRuntimeData = new NodeRuntimeData(this, parentNodeRuntimeData)) { myNodeRuntimeData.tickExecuteEnumerator = children[0].Tick(myNodeRuntimeData, recursions + 1).GetEnumerator(); myNodeRuntimeData.taskHasChanges = base.PreTick(NodeExecute.Run, myNodeRuntimeData); // the second check of myNodeRuntimeData.tickExecuteEnumerator is intended, as movenext may destroy it while ((myNodeRuntimeData.tickExecuteEnumerator != null) && myNodeRuntimeData.tickExecuteEnumerator.MoveNext()) { // if (myNodeRuntimeData == null) { // Debug.LogError(NodeLogger("RunTreeNode.Tick", $"myNodeRuntimeData is null")); // } if (myNodeRuntimeData.tickExecuteEnumerator == null) { Debug.LogError(NodeLogger("RunTreeNode.Tick", $"myNodeRuntimeData.tickExecuteEnumerator is null, movenext destroyed it")); break; } myNodeRuntimeData.nodeResult = myNodeRuntimeData.tickExecuteEnumerator.Current; if (debugInternalActive) Debug.Log(NodeLogger($"Tick.before", $"nodeResult {myNodeRuntimeData.nodeResult}")); // return the same result as the child myNodeRuntimeData.taskHasChanges |= base.PostTick(NodeExecute.Run, myNodeRuntimeData); if (myNodeRuntimeData.taskHasChanges && taskController) { if (debugChangesActive) Debug.Log(NodeLogger($"Tick", $"changed to {myNodeRuntimeData.nodeResult}")); taskController.SetUiUpdate(); } yield return myNodeRuntimeData.nodeResult; // this should not be run again if it isnt in runnning mode anymore if (myNodeRuntimeData.nodeState == NodeState.Running) { if (debugChangesActive) Debug.Log(NodeLogger($"Tick.Cleanup", $"changed to {myNodeRuntimeData.nodeResult}")); myNodeRuntimeData.taskHasChanges = PreTick(NodeExecute.Run, myNodeRuntimeData); } else { if (debugChangesActive) Debug.Log(NodeLogger($"Tick.Cleanup", $"Testing, should be executed once after success of enumerator")); } } } } else { Debug.LogError(NodeLogger("RunTreeNode.Tick", $"recursions {recursions} childCount {children.Count}")); taskController.SetUiUpdate(); yield return NodeResult.Error; } yield break; } public override string ToString() { return base.ToString() + " thisId: " + this.GetInstanceID(); } public override Node Duplicate() { TreeNode tn = ScriptableObject.CreateInstance(); base.BaseDuplicate(tn); // TreeNode tn = base.Duplicate() as TreeNode; tn.treeNodeName = treeNodeName; return tn; } } }