/// <summary> /// Run our selected child. If no child is selected, select one. If can't select one, return false. /// </summary> /// <param name="tank">Tank being controlled.</param> /// <returns>Whether we want to continue running.</returns> public override bool Tick(AIInput g) { BehaviorTreeNode next = SelectChild(g); //Debug.Log(next); if (next == null) { return(false); } if (selected != next) { Deactivate(g); next.Activate(g); selected = next; } bool response = next.Tick(g); if (response == false) { Deactivate(g); sequentialChild++; sequentialChild %= Children.Count; } return(response); }
public void RefreshChild(RootNode _Root, BehaviorTreeNode _Node) { if (_Node.m_ChildNode == null || _Node.m_ChildNode.Count < 1) { ActionNode a = _Node as ActionNode; if (a != null) { _Root.m_ListActionNode.Add(a); } return; } for (int i = 0; i < _Node.m_ChildNode.Count; ++i) { _Node.m_RootNode = _Root; if (_Node.m_ChildNode[i] == null) { _Node.m_ChildNode.RemoveAt(i); } else { RefreshChild(_Root, _Node.m_ChildNode[i]); } } }
void DrawChildNode(BehaviorTreeNode _Node) { if (_Node.m_ChildNode == null) { return; } //string[] split = _Node.ToString().Split('('); //string[] split2 = split[1].Split(')'); if (_Node.m_ChildNode.Count > 0 && (m_ListIsFoldout[m_FoldIndex] = EditorGUILayout.Foldout(IsFoldout(m_FoldIndex++), "branch"))) { GUI.backgroundColor = Color.cyan; EditorGUI.indentLevel += 2; for (int i = 0; i < _Node.m_ChildNode.Count; ++i) { //GUI.color = Color.cyan; _Node.m_ChildNode[i] = EditorGUILayout.ObjectField(_Node.m_ChildNode[i], typeof(BehaviorTreeNode), false) as BehaviorTreeNode; //GUI.color = Color.white; if (_Node.m_ChildNode[i] != null) { if (_Node.m_ChildNode[i].m_ChildNode != null) { DrawChildNode(_Node.m_ChildNode[i]); } } //else //{ // _Node.m_ChildNode.RemoveAt(i); //} } EditorGUI.indentLevel -= 2; } //GUILayout.Space(5.0f); }
// <summary> /// /// </summary> /// <returns></returns> public override BehaviorReturnCode Run() { if (_children.Count == 0) { return(BehaviorReturnCode.BT_SUCCESS); } if (_currentPosition == -1) { Init(); } System.Random random = new System.Random(DateTime.Now.Millisecond); int randomNumber = 0; BehaviorReturnCode status = BehaviorReturnCode.BT_FAILURE; if (_currentPosition == -1) { randomNumber = random.Next(0, _children.Count); } else { randomNumber = _currentPosition; } BehaviorTreeNode currentRunningNode = _children[randomNumber]; status = currentRunningNode.Run(); if (status == BehaviorReturnCode.BT_SUCCESS || status == BehaviorReturnCode.BT_FAILURE) { _currentPosition = -1; } return(status); }
public override STATUS Execute() { Debug.Log("[ProbabilityBT]"); STATUS finalStatus; // This means that in the previous execution the choosen node // returned RUNNING if(mp_CurrentNode != null) { finalStatus = mp_CurrentNode.Execute(); if(finalStatus != STATUS.RUNNING) mp_CurrentNode = null; return finalStatus; } Init(); float randomWeight = Random.Range(0f, mf_TotalWeigth); float weightSum = 0f; foreach(KeyValuePair<BehaviorTreeNode, float> weightTuple in md_WeightList) { weightSum += weightTuple.Value; if(randomWeight <= weightSum) { mp_CurrentNode = weightTuple.Key; finalStatus = mp_CurrentNode.Execute(); if(finalStatus != STATUS.RUNNING) mp_CurrentNode = null; return finalStatus; } } return STATUS.ERROR; }
/// <summary> /// /// </summary> /// <param name="runLimit"></param> /// <param name="child"></param> public Limit(int runLimit, BehaviorTreeNode child) { _children = new List <BehaviorTreeNode>(1); _children.Add(child); _runLimit = runLimit; _count = 0; }
/// <summary> /// Run our selected child. If no child is selected, select one. If can't select one, return false. /// </summary> /// <param name="tank">Tank being controlled.</param> /// <returns>Whether we want to continue running.</returns> public override bool Tick(AITankControl tank) { // Fill me in BehaviorTreeNode s_child = SelectChild(tank); if (s_child != null) { if (s_child != selected) { Deactivate(tank); selected = s_child; Activate(tank); } bool tick_val = selected.Tick(tank); if (tick_val == false) { Deactivate(tank); selected = null; } return(true); } else { return(false); } }
/// <summary> /// Run the specified decider and returns its value /// </summary> /// <param name="d">Decider to run</param> /// <param name="tank">Tank being controlled</param> /// <returns>True if decider wants to run</returns> public static bool Decide(this DeciderType d, AITankControl tank) { switch (d) { case DeciderType.Always: return(true); case DeciderType.TooManyBullets: return(Physics2D.OverlapCircleAll(tank.transform.position, BulletSearchRadius, (int)Layers.Projectiles).Length > MaxBullets); case DeciderType.LineOfSightToPlayer: return(!BehaviorTreeNode.WallBetween(tank.transform.position, BehaviorTreeNode.Player.position)); case DeciderType.CanFire: float angle = Vector2.Angle(BehaviorTreeNode.Player.position - tank.transform.position, tank.transform.up); return(angle < MaxAngularDifference && Vector2.Distance(tank.transform.position, BehaviorTreeNode.Player.position) < DistanceThreshold); default: throw new ArgumentException("Unknown Decider: " + d); } }
private void ShowFields(BehaviorTreeNode node) { foreach (var f in node.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy)) { PropertyField(node, f); } }
private void ShowTreeNode(BehaviorTreeNode node) { EditorGUILayout.BeginHorizontal(); if (!foldouts.ContainsKey(node)) { foldouts[node] = false; } foldouts[node] = EditorGUILayout.Foldout(foldouts[node], node.GetType().Name); var newName = EditorGUILayout.TextField(node.name); if (newName != node.name) { Undo.RecordObject(node, "set name"); node.name = newName; } EditorGUILayout.EndHorizontal(); if (foldouts[node]) { ShowFields(node); var d = node as GroupDecider; if (d) { ShowChildren(d); } } }
/// <summary> /// /// </summary> /// <returns></returns> public override BehaviorReturnCode Run() { if (_children.Count == 0) { return(BehaviorReturnCode.BT_SUCCESS); } if (_currentPosition == -1) { Init(); } BehaviorTreeNode currentRunningNode = _children[_currentPosition]; BehaviorReturnCode status = BehaviorReturnCode.BT_FAILURE; while ((status = currentRunningNode.Run()) == BehaviorReturnCode.BT_SUCCESS) { _currentPosition++; // Fallan todos los hijos if (_currentPosition == _children.Count) { _currentPosition = -1; return(status); } currentRunningNode = _children[_currentPosition]; } if (status == BehaviorReturnCode.BT_FAILURE) { _currentPosition = -1; } return(status); }
//-------------------------------------------------- // Overrided/Overloaded methods //-------------------------------------------------- #region OVERRIDED_OVERLOADED_METHODS public override BehaviorTree Add (BehaviorTreeNode btNode) { DebugHelp.Assert(ml_Nodes.Count < 2, "[ERROR] ConditionalBT only needs two children."); base.Add(btNode); return this; }
//-------------------------------------------------- // Overrided/Overloaded methods //-------------------------------------------------- #region OVERRIDED_OVERLOADED_METHODS public override BehaviorTree Add(BehaviorTreeNode btNode) { DebugHelp.Assert(ml_Nodes.Count < 2, "[ERROR] ConditionalBT only needs two children."); base.Add(btNode); return(this); }
/// <summary> /// We're not running anymore; recursively deactivate our selected child. /// </summary> /// <param name="tank">Tank being controlled</param> public override void Deactivate(AITankControl tank) { if (selected) { selected.Deactivate(tank); selected = null; } }
public void Add(string type, BehaviorTreeNode n) { var e = new Event(); e.type = type; e.node = n; events.Add(e); }
/// <summary> /// We're not running anymore; recursively deactivate our selected child. /// </summary> /// <param name="tank">Tank being controlled</param> public override void Deactivate(AIInput g) { if (selected) { selected.Deactivate(g); selected = null; } }
public Wait(float duration, TimerDelegate dlg, BehaviorTreeNode child) { _children = new List <BehaviorTreeNode>(1); _children.Add(child); _waitTime = duration; _count = 0; _timerDlg = dlg; }
/// <summary> /// Initializes a new instance of the <see cref="ConditionalNode"/> class. /// </summary> /// <param name="conditional">The conditional function.</param> /// <param name="trueNode">The node that will execute when true.</param> /// <param name="falseNode">The node that will execute when false.</param> public ConditionalNode( Func <Blackboard, bool> conditional, BehaviorTreeNode trueNode = null, BehaviorTreeNode falseNode = null) { this.Conditional = conditional ?? throw new ArgumentNullException(nameof(conditional)); this.TrueNode = trueNode; this.FalseNode = falseNode; }
/// <summary> /// Initializes a new instance of the <see cref="TimeoutNode"/> class. /// </summary> /// <param name="child">The child node.</param> /// <param name="timeout">The amount of time this node has until it times out.</param> public TimeoutNode(BehaviorTreeNode child, TimeSpan timeout) { if (timeout == TimeSpan.MinValue) { throw new ArgumentOutOfRangeException(nameof(timeout)); } this.Child = child ?? throw new ArgumentNullException(nameof(child)); this.Timeout = timeout; }
/// <summary> /// Initializes a new instance of the <see cref="TimerNode"/> class. /// </summary> /// <param name="child">The child.</param> /// <param name="sleepTime">The amount of time in seconds that we will wait.</param> /// <param name="durationKey">Blackboard Property key for storing the current duration.</param> /// <param name="failureCode">The code that will return when the duration is hit.</param> public TimerNode( BehaviorTreeNode child, float sleepTime, string durationKey = null, BehaviorReturnCode failureCode = BehaviorReturnCode.Running) { this.Child = child ?? throw new ArgumentNullException(nameof(child)); this.SleepTime = sleepTime; this.DurationKey = durationKey ?? Guid.ToString(); this.FailureCode = failureCode; }
/// <summary> /// Initializes a new instance of the <see cref="RandomDecoratorNode"/> class. /// </summary> /// <param name="child">The child.</param> /// <param name="probability">The probability that it will execute.</param> /// <param name="function">The random function.</param> /// <param name="failureCode">The code that will return if it wont execute.</param> public RandomDecoratorNode( BehaviorTreeNode child, float probability, Func <Blackboard, float> function = null, BehaviorReturnCode failureCode = BehaviorReturnCode.Failure) { this.Child = child ?? throw new ArgumentNullException(nameof(child)); this.Probability = probability; this.Function = function ?? RandomProbability; this.FailureCode = failureCode; }
BehaviorTreeNode BuildNode(Behavior behavior) { var node = new BehaviorTreeNode(behavior); foreach (var child in behavior.GetChildren()) { node.Nodes.Add(BuildNode(child)); } return(node); }
/// <summary> /// Initializes a new instance of the <see cref="RepeatNode"/> class. /// </summary> /// <param name="child">The child node.</param> /// <param name="times">The amount of times this will be executed at once.</param> /// <param name="timesKey">The blackboard property key that will contain the how many times it has executed.</param> public RepeatNode(BehaviorTreeNode child, int times, string timesKey = null) { if (times <= 0) { throw new ArgumentOutOfRangeException(nameof(times)); } this.Child = child ?? throw new ArgumentNullException(nameof(child)); this.Times = times; this.TimesKey = timesKey; }
/// <summary> /// Reorder the children pseudo-randomly /// </summary> private void Shuffle() { int n = _children.Count; System.Random rnd = new System.Random(); while (n > 1) { int k = (rnd.Next(0, n) % n); n--; BehaviorTreeNode value = _children[k]; _children[k] = _children[n]; _children[n] = value; } }
/// <summary> /// Initializes a new instance of the <see cref="RetryNode"/> class. /// </summary> /// <param name="child">The child node.</param> /// <param name="maxAttempts">The max attempts this node will be executed.</param> /// <param name="attemptKey">The blackboard property key that will contain the how many attempts have passed.</param> /// <param name="failureCode">The code that will return if exceed max attempts.</param> public RetryNode( BehaviorTreeNode child, int maxAttempts, string attemptKey = null, BehaviorReturnCode failureCode = BehaviorReturnCode.Failure) { if (maxAttempts <= 0) { throw new ArgumentOutOfRangeException(nameof(maxAttempts)); } this.Child = child ?? throw new ArgumentNullException(nameof(child)); this.MaxAttempts = maxAttempts; this.AttemptKey = attemptKey; this.FailureCode = failureCode; }
/// <summary> /// Select a child to run based on the policy. /// </summary> /// <param name="tank">Tank being controlled</param> /// <returns>Child to run, or null if no runnable children.</returns> private BehaviorTreeNode SelectChild(AIInput g) { switch (Policy) { case SelectionPolicy.Prioritized: for (int i = 0; i < Children.Count; i++) { BehaviorTreeNode child = Children[i]; //Debug.Log(child +" - "+i); if (selected == child) { return(child); } if (child.Decide(g)) { return(child); } } //Debug.Log("none"); return(null); case SelectionPolicy.Sequential: for (int i = 0; i < Children.Count; i++) { int j = (i + sequentialChild) % Children.Count; BehaviorTreeNode child = Children[j]; //Debug.Log(child +" - "+i); if (selected == child) { return(child); } if (child.Decide(g)) { sequentialChild = j; return(child); } } //Debug.Log("none"); return(null); default: throw new NotImplementedException("Unimplemented policy: " + Policy); } }
/// <summary> /// Compute the Neighbors list /// </summary> internal void Start() { var position = transform.position; if (AllWaypoints == null) { AllWaypoints = FindObjectsOfType <Waypoint>(); } foreach (var wp in AllWaypoints) { if (wp != this && !BehaviorTreeNode.WallBetween(position, wp.transform.position)) { Neighbors.Add(wp); } } }
/// <summary> /// Nearest waypoint to specified location that is reachable by a straight-line path. /// </summary> /// <param name="position"></param> /// <returns></returns> public static Waypoint NearestWaypointTo(Vector2 position) { Waypoint nearest = null; var minDist = float.PositiveInfinity; for (int i = 0; i < AllWaypoints.Length; i++) { var wp = AllWaypoints[i]; var p = wp.transform.position; var d = Vector2.Distance(position, p); if (d < minDist && !BehaviorTreeNode.WallBetween(p, position)) { nearest = wp; minDist = d; } } return(nearest); }
public override STATUS Execute() { Debug.Log("[ProbabilityBT]"); STATUS finalStatus; // This means that in the previous execution the choosen node // returned RUNNING if (mp_CurrentNode != null) { finalStatus = mp_CurrentNode.Execute(); if (finalStatus != STATUS.RUNNING) { mp_CurrentNode = null; } return(finalStatus); } Init(); float randomWeight = Random.Range(0f, mf_TotalWeigth); float weightSum = 0f; foreach (KeyValuePair <BehaviorTreeNode, float> weightTuple in md_WeightList) { weightSum += weightTuple.Value; if (randomWeight <= weightSum) { mp_CurrentNode = weightTuple.Key; finalStatus = mp_CurrentNode.Execute(); if (finalStatus != STATUS.RUNNING) { mp_CurrentNode = null; } return(finalStatus); } } return(STATUS.ERROR); }
/// <summary> /// Initializes a new instance of the <see cref="CounterNode"/> class. /// </summary> /// <param name="child">The child node.</param> /// <param name="maxCount">The number of times this node will be exectued.</param> /// <param name="counterKey">Blackboard Property key for storing the current counter index.</param> public CounterNode(BehaviorTreeNode child, int maxCount, string counterKey = null) { this.Child = child ?? throw new ArgumentNullException(nameof(child)); this.MaxCount = maxCount; this.CounterKey = counterKey ?? Guid.ToString(); }
public override BehaviorTree Add(BehaviorTreeNode btNode) { Add (btNode, 1f); return this; }
public void Add(BehaviorTreeNode btNode, float weight) { md_WeightList.Add(new KeyValuePair<BehaviorTreeNode, float>(btNode, weight)); mf_TotalWeigth += weight; }
public void AddChild(BehaviorTreeNode child) { ChildNodes = child; }
public override void Init() { base.Init(); mp_CurrentNode = null; }
//-------------------------------------------------- // Public Methods //-------------------------------------------------- #region PUBLIC_METHODS public virtual BehaviorTree Add(BehaviorTreeNode btNode) { ml_Nodes.Add(btNode); return(this); }
public virtual BehaviorTree Add(BehaviorTreeNode btNode) { ml_Nodes.Add(btNode); return this; }