//============= Copyright (c) Ludic GmbH, All rights reserved. ============== // // Purpose: Part of the My Behaviour Tree Code // //============================================================================= using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Runtime.Serialization.Formatters.Binary; using System.Xml.Serialization; using UnityEngine; namespace MyBT { public enum Actions { Idle, Log, RestartBehaviourTree, StartBehaviourTree, StopBehaviourTree, Wait } public class ActionNode : Node { [SerializeField] public string functionName; [SerializeField] public TaskParameterGroup taskParameterGroup; // cannot be seralized [NonSerialized] public Action action; public void Init (int _nodeDepth, Token[] _tokens, string _functionName, TaskParameterGroup _taskParameterGroup) { base.Init(_nodeDepth, _tokens); functionName = _functionName; taskParameterGroup = _taskParameterGroup; } /// /// reset the whole behaviour tree structure /// public override void Destroy() { Debug.Log(NodeLogger($"Destroy", "")); base.Destroy(); action = null; taskParameterGroup = null; functionName = ""; base.Destroy(); } public bool isBound { get { return action != null; } } public override void Execute (NodeRuntimeData myNodeRuntimeData, NodeExecute nodeExecute) { ActionNodeRuntimeData actionNodeRuntimeData = (ActionNodeRuntimeData)myNodeRuntimeData; actionNodeRuntimeData.taskHasChanges = base.PreTick(nodeExecute, actionNodeRuntimeData); // clear data on firstrun if (actionNodeRuntimeData.nodeState == NodeState.FirstRun) { actionNodeRuntimeData.Clear(); } //actionNodeRuntimeData.taskResult = actionNodeRuntimeData.nodeResult; Task.currentNode = this; Task.currentNodeRuntimeData = actionNodeRuntimeData; // run action // executing the action might change: logString, userData or taskResult of this node if (action != null) { try { //if (debugInternalActive) Debug.Log(NodeLogger($"Tick.{nodeExecute}.BeforeAction", $"nodeState {actionNodeRuntimeData.nodeState} nodeResult {actionNodeRuntimeData.nodeResult} taskResult {actionNodeRuntimeData.taskResult}")); action(); //if (debugInternalActive) Debug.Log(NodeLogger($"Tick.{nodeExecute}.AfterAction", $"nodeState {actionNodeRuntimeData.nodeState} nodeResult {actionNodeRuntimeData.nodeResult} taskResult {actionNodeRuntimeData.taskResult}")); } catch (Exception ex) { Debug.LogError(NodeLogger($"Tick.{nodeExecute}", $"Exception in Action \"{codeLine}({taskParameterGroup})\" {(tokens.Length > 0 ? $"{tokens[0].location.line}:{tokens[0].location.col}" : "undefined")} caused an Exception!\n===\n{ex.InnerException}\n===\n{ex}\n===\n")); // Debug.LogError($"ex.Data:\n{ex.Data}\n\nex.InnerException.Message:\n{ex.InnerException}\n\nex.Message:\n{ex.Message}\n\nex:\n{ex}"); actionNodeRuntimeData.nodeResult = NodeResult.Error; } } else { Debug.LogError(NodeLogger($"Tick.{nodeExecute}", $"Action is undefined")); } if (debugInternalActive && (actionNodeRuntimeData.nodeResult == NodeResult.Error)) { Debug.LogError(NodeLogger($"Tick.{nodeExecute}", $"taskResult {actionNodeRuntimeData.nodeResult}")); } // update task and node according to each others changes actionNodeRuntimeData.taskHasChanges |= base.PostTick(nodeExecute, actionNodeRuntimeData); if (actionNodeRuntimeData.taskHasChanges && taskController) { taskController.SetUiUpdate(); } if (debugInternalActive) Debug.Log(NodeLogger($"Tick.{nodeExecute}.Last", $"nodeState {actionNodeRuntimeData.nodeState} nodeResult {actionNodeRuntimeData.nodeResult}")); } public override IEnumerable Tick(NodeRuntimeData parentNodeRuntimeData, int recursions = 0) { if (debugInternalActive) Debug.Log(NodeLogger($"Tick", $"recursions {recursions}")); if ((action != null)) { using (ActionNodeRuntimeData myNodeRuntimeData = new ActionNodeRuntimeData(this, parentNodeRuntimeData)) { do { Execute(myNodeRuntimeData, NodeExecute.Run); yield return myNodeRuntimeData.nodeResult; } while (myNodeRuntimeData.nodeResult == NodeResult.Continue); if (debugInternalActive) Debug.Log(NodeLogger($"Tick.Finished", $"taskResult {myNodeRuntimeData.nodeResult}")); } } else { Debug.LogError(NodeLogger("Tick", $"action undefined?")); yield return NodeResult.Error; } yield break; } public override Node Duplicate () { ActionNode tn = ScriptableObject.CreateInstance(); base.BaseDuplicate (tn); tn.functionName = functionName; tn.taskParameterGroup = taskParameterGroup.Duplicate(); tn.action = action; return tn; } public override string ToString() { return base.ToString(); } } }