public void AddChild(BehaviourNode child) { switch (Type) { case NodeType.TASK: throw new System.Exception($"Failed to add {child.Name}. Tasks don`t have children"); case NodeType.DECORATOR: if (Children.Count > 1) { throw new System.Exception($"Failed to add {child.Name} to {Name}. Too many children"); } break; } if (!_children.Contains(child)) { if (child.Parent != null) { throw new System.Exception($"Adding child to {Name} failed. {child.Name} already has parent {child.Parent.Name}"); } _children.Add(child); child.SetParent(this); OnChildNodeAdded.Invoke(this, child); } }
private void OnChildNodeStoppedSilent_Listener(BehaviourNode child, bool success) { if (m_isLimitReached || (!success && !m_waitOnFailure)) { RemoveTimer(m_timeoutTimer); } }
private void OnChildNodeStopped_Listener(BehaviourNode child, bool success) { OnChildNodeStopped_Common(child, success); // OnStopped.Invoke(success); // StopNode(success); StopNodeOnNextTick(success); }
private void OnChildNodeStopped_Common(BehaviourNode child, bool child_success, bool silent) { int child_count = Children.Count(); if (child_success) { m_succeededCount++; } else { m_failedCount++; } bool allChildrenStarted = RunningChildrenCount + m_succeededCount + m_failedCount == child_count; if (allChildrenStarted) { if (RunningChildrenCount == 0) { if (m_failureStopCondition == StopCondition.ONE_CHILD && m_failedCount > 0) { m_success = false; } else if (m_successStopCondition == StopCondition.ONE_CHILD && m_succeededCount > 0) { m_success = true; } else if (m_successStopCondition == StopCondition.ALL_CHILDREN && m_succeededCount == child_count) { m_success = true; } else { m_success = false; } if (!silent) { // OnStopped.Invoke(m_success); // StopNode(m_success); StopNodeOnNextTick(m_success); } } else if (!m_stoppedByChildren) { if (m_failureStopCondition == StopCondition.ONE_CHILD && m_failedCount > 0) { m_success = false; m_stoppedByChildren = true; if (!silent) { // StopChildren(); RunOnNextTick(StopChildren); } } } } }
/// <summary> /// Common logic for all MonoBehaviour Update functions /// </summary> /// <param name="updateType"></param> private void UpdateCommon(BehaviourNode.UpdateType updateType) { if (Paused) { return; } // BehaviourNode.UpdateTime(Time.deltaTime); BehaviourNode.OverrideElapsedTime(Time.time); CurrentTree?.UpdateRecursively(updateType); }
private void OnChildNodeStopped_Listener(BehaviourNode child, bool success) { if (m_isLimitReached || (!success && !m_waitOnFailure)) { RemoveTimer(m_timeoutTimer); // OnStopped.Invoke(success); // StopNode(success); RunOnNextTick(() => { StopNode(false); }); } }
/// <summary> /// Get the deepest nodes in children /// </summary> public BehaviourNode[] GetLeaves(NodeState?nodeState = null) { var result = GetLeavesFromChildren(nodeState).ToArray(); if (result.Length <= 0 && (nodeState == null || State == nodeState)) { result = new BehaviourNode[] { this }; } return(result); }
private void OnChildNodeStopped_Listener(BehaviourNode child, bool success) { if (State != NodeState.STOPPING) { // wait one tick, to prevent endless recursions m_rootTimer = StartFirstChildNodeOnNextTick(); } else { StopNodeOnNextTick(success); } }
/// <summary> /// This is used for network peers, it tries to /// turn on/off behaviour nodes to match the BehaviourNodes /// of the host /// </summary> /// <param name="silent">If true will not invoke the OnStarted event</param> public bool SyncActiveLeaves(string[] nodeIDs, bool silent = true) { LastResyncNodeIDs = nodeIDs; var activeLeaves = new BehaviourNode[nodeIDs.Length]; for (int i = 0; i < nodeIDs.Length; i++) { activeLeaves[i] = GetNodeByID(nodeIDs[i]); } return(SyncActiveLeaves(activeLeaves, silent)); }
/* * public override bool RequestStopNode(bool silent = false) * { * if (base.RequestStopNode(silent)) * { * m_isReady = true; * RemoveTimer(m_timeoutTimer); * if (!silent) * { * if (Children[0].State == NodeState.ACTIVE) * { * Children[0].RequestStopNode(); * } * else * { * // OnStopped.Invoke(false); * StopNode(false); * } * } * return true; * } * return false; * } */ private void OnChildNodeStopped_Common(BehaviourNode child, bool success) { if (m_resetOnFailiure && !success) { m_isReady = true; RemoveTimer(m_timeoutTimer); } else if (m_startAfterChild) { AddTimer(m_cooldownTime, m_randomVariation, 0, OnTimeout); } }
/// <summary> /// Check if node is within path to this node /// </summary> public bool IsMyAncestor(BehaviourNode node) { if (this.Parent == null) { return(false); } else if (node == this.Parent) { return(true); } return(this.Parent.IsMyAncestor(node)); }
public void RestartChild(BehaviourNode child) { if (!Children.Contains(child)) { throw new System.Exception("Not parent of this child!"); } if (child.Result == true) { m_succeededCount--; } else { m_failedCount--; } child.StartNode(); }
private void OnChildNodeStopped_Listener(BehaviourNode child, bool success) { OnChildNodeStopped_Common(child, success); if (m_isLimitReached) { // OnStopped.Invoke(false); // StopNode(false); StopNodeOnNextTick(false); } else { // OnStopped.Invoke(success); // StopNode(success); StopNodeOnNextTick(success); } }
/* * private void DrawBehaviourTree(Debugger debugger) * { * EditorGUILayout.BeginVertical(); * { * GUILayout.Label("Behaviour Tree:", EditorStyles.boldLabel); * * EditorGUILayout.BeginVertical(nestedBoxStyle); * DrawNodeTree(debugger.BehaviorTree, 0); * EditorGUILayout.EndVertical(); * } * EditorGUILayout.EndVertical(); * } */ protected override void DrawNodeButtons(BehaviourNode node) { if (node.State == BehaviourNode.NodeState.ACTIVE) { if (GUILayout.Button("stop", EditorStyles.miniButton)) { node.RequestStopNode(); } } else if (node is BehaviourRootNode && node.State == BehaviourNode.NodeState.INACTIVE) { GUI.color = new Color(1f, 1f, 1f, 1f); if (GUILayout.Button("start", EditorStyles.miniButton)) { node.StartNode(); } GUI.color = new Color(1f, 1f, 1f, 0.3f); } }
public BehaviourDebugTools(BehaviourNode node, string GUItag = "") { ResetValues(); m_node = node; switch (node.Type) { /* * case BehaviourNode.NodeType.ROOT: * NodeColor = ROOT_COLOR; * break; */ case BehaviourNode.NodeType.COMPOSITE: NodeColor = COMPOSITE_COLOR; break; case BehaviourNode.NodeType.DECORATOR: NodeColor = (node is Decorator.BehaviourObserver) ? OBSERVER_COLOR : DECORATOR_COLOR; break; case BehaviourNode.NodeType.TASK: NodeColor = TASK_COLOR; break; } if (m_node is BehaviourRootNode) { NodeColor = ROOT_COLOR; } node.OnStarted.AddListener(OnStarted_Listener); node.OnStartedSilent.AddListener(OnStarted_Listener); node.OnStopping.AddListener(OnStopping_Listener); node.OnStoppingSilent.AddListener(OnStopping_Listener); node.OnStopped.AddListener(OnStopped_Listener); node.OnStoppedSilent.AddListener(OnStopped_Listener); }
public int GetIndexOfChild(BehaviourNode child) { return(_children.IndexOf(child)); }
private void OnChildNodeStopped_Common(BehaviourNode child, bool success) { RemoveTimer(m_timeoutTimer); }
/// <summary> /// Run child node immediately, but only if last execution wasn't at least past cooldownTime. /// </summary> /// <param name="cooldownTime">The cooldown time</param> /// <param name="decoratee">The child node</param> /// <param name="randomVariation">The random variation to the cooldown time</param> /// <param name="startAfterChild">Start the cooldown after the child node stops</param> /// <param name="resetOnFailiure">If true, the cooldown will be reset if the child node fails</param> public BehaviourCooldown(float cooldownTime, BehaviourNode decoratee, float randomVariation, bool startAfterChild, bool resetOnFailiure) : base("Cooldown", NodeType.DECORATOR) { AddChild(decoratee); Init(cooldownTime, randomVariation, startAfterChild, resetOnFailiure); }
/// <summary> /// Run child node immediately, but only if last execution wasn't at least past cooldownTime. /// </summary> /// <param name="cooldownTime">The cooldown time</param> /// <param name="decoratee">The child node</param> /// <param name="randomVariation">The random variation to the cooldown time</param> public BehaviourCooldown(float cooldownTime, BehaviourNode decoratee, float randomVariation) : base("Cooldown", NodeType.DECORATOR) { AddChild(decoratee); Init(cooldownTime, randomVariation); }
private void OnChildNodeStoppedSilent_Listener(BehaviourNode child, bool child_success) { OnChildNodeStopped_Common(child, child_success, true); }
/// <summary> /// Run child node immediately, but only if last execution wasn't at least past cooldownTime. /// </summary> /// <param name="cooldownTime">The cooldown time</param> /// <param name="decoratee">The child node</param> public BehaviourCooldown(float cooldownTime, BehaviourNode decoratee) : base("Cooldown", NodeType.DECORATOR) { AddChild(decoratee); Init(cooldownTime); }
public bool HasChild(BehaviourNode node) { return(Children.Contains(node)); }
public void RemoveChild(BehaviourNode child) { child.SetParent(null); _children.Remove(child); OnChildNodeRemoved.Invoke(this, child); }
/// <summary> /// Run child node immediately, but only if last execution wasn't at least past cooldownTime. /// </summary> /// <summary> /// Run child node immediately, but only if last execution wasn't at least past cooldownTime. /// </summary> /// <param name="cooldownTime">The cooldown time</param> /// <param name="decoratee">The child node</param> /// <param name="startAfterChild">Start the cooldown after the child node stops</param> /// <param name="resetOnFailiure">If true, the cooldown will be reset if the child node fails</param> /// <param name="failOnCooldown">If true, fail instead of wait in case the cooldown is still active</param> public BehaviourCooldown(float cooldownTime, BehaviourNode decoratee, bool startAfterChild, bool resetOnFailiure, bool failOnCooldown) : base("Cooldown", NodeType.DECORATOR) { AddChild(decoratee); Init(cooldownTime, null, startAfterChild, resetOnFailiure, failOnCooldown); }