// A Selector may be contaminated with other nodes (Condition) or IParentBeahviourTreeNodes over which // it's behaviour as a selector is applied. The assumption here is that any item in it's child list // should have selector behaviour applied unless the first one is a condition Action. public BehaviourTreeStatus Tick(TimeData time) { int skipOne = 0; // check if this is a conditional action IBehaviourTreeNode firstNode = children[0]; if (firstNode is ConditionNode) { ConditionNode firstChild = (ConditionNode)firstNode; var status = firstChild.Tick(time); if (status != BehaviourTreeStatus.Success) { return(BehaviourTreeStatus.Success); } ++skipOne; } List <IBehaviourTreeNode> remainingChildren = children.Skip(skipOne).ToList <IBehaviourTreeNode>(); if (isRandom) { remainingChildren = Randomize(remainingChildren); } foreach (var child in remainingChildren) { var childStatus = child.Tick(time); if (childStatus != BehaviourTreeStatus.Failure) { return(childStatus); } } return(BehaviourTreeStatus.Failure); }
/// <summary> /// Like an action node... but the function can return true/false and is mapped to success/failure. /// </summary> public BehaviourTreeBuilder Condition(string name, Func <TimeData, bool> fn) { if (parentNodeStack.Count <= 0) { throw new ApplicationException("Can't create an unnested ActionNode, it must be a leaf node."); } var conditionNode = new ConditionNode(name, fn); parentNodeStack.Peek().AddChild(conditionNode); return(this); }
// A Selector may be contaminated with other nodes (Condition) or IParentBeahviourTreeNodes over which // it's behaviour as a selector is applied. The assumption here is that any item in it's child list // should have selector behaviour applied unless the first one is a condition Action. public IEnumerator <BehaviourTreeStatus> Tick(TimeData time) { int skipOne = 0; // check if this is a conditional action IBehaviourTreeNode firstNode = children[0]; if (firstNode is ConditionNode) { ConditionNode firstChild = (ConditionNode)firstNode; var status = firstChild.Tick(time); status.MoveNext(); if (status.Current != BehaviourTreeStatus.Success) { // Return Failure and Exit the Node currentStatus = BehaviourTreeStatus.Failure; yield return(currentStatus); yield break; } else { ++skipOne; } } List <IBehaviourTreeNode> remainingChildren = children.Skip(skipOne).ToList <IBehaviourTreeNode>(); if (isRandom) { remainingChildren = Randomize(remainingChildren); } foreach (var child in remainingChildren) { var childStatus = child.Tick(time); childStatus.MoveNext(); currentStatus = childStatus.Current; if (isRunning()) { // keep looping until we exit running mode or we // run out of enum values. yield return(currentStatus); while (childStatus.MoveNext()) { currentStatus = childStatus.Current; if (!isRunning()) { break; } } } // On exit above, status should be success or fail // if success, then exit selector if (isSuccess()) { yield return(currentStatus); yield break; } } yield return(currentStatus); }