/// <summary> /// Creates a transition between one <see cref="BehaviourTreeEngine"/>, the submachine; and another <see cref="BehaviourTreeEngine"/>, the supermachine. /// </summary> /// <param name="name">The name of the transition</param> /// <param name="nodeFrom">The exit node of the transition</param> /// <param name="stateTo">The node where the Behaviour tree is coming back</param> /// <param name="superMachine">The supermachine</param> /// <param name="subMachine">The submachine</param> public Transition(string name, TreeNode nodeFrom, LeafNode stateTo, BehaviourTreeEngine superMachine, BehaviourTreeEngine subMachine) { this.Name = name; this.StateFrom = nodeFrom.StateNode; this.StateTo = stateTo.StateNode; this.Perception = new OrPerception(new BehaviourTreeStatusPerception(subMachine, ReturnValues.Succeed, subMachine), new BehaviourTreeStatusPerception(subMachine, ReturnValues.Failed, subMachine), subMachine); this.type = TRANSITION_TYPE.SUPER_TRANSITION; if (StateFrom.BehaviourEngine == superMachine) // Exits from the super-machine { this.BehaviourEngine = superMachine; Perception.SetBehaviourMachine(superMachine); superMachine.Configure(StateFrom) .OnExit(this.Name, () => Perception.Reset()) .InternalTransition(Perception, this.Name, () => ExitTransition(StateFrom, stateTo, subMachine.GetRootNode().ReturnValue, subMachine.GetState("Entry_Machine"), superMachine, subMachine)); } else // Exits from the sub-machine { this.BehaviourEngine = subMachine; Perception.SetBehaviourMachine(subMachine); subMachine.Configure(StateFrom) .OnExit(this.Name, () => Perception.Reset()) .InternalTransition(Perception, this.Name, () => ExitTransition(StateFrom, stateTo, subMachine.GetRootNode().ReturnValue, subMachine.GetState("Entry_Machine"), superMachine, subMachine)); } }
public SucceederDecoratorNode(string name, TreeNode child, BehaviourTreeEngine behaviourTree) { base.Child = child; Child.ParentNode = this; base.StateNode = new State(name, () => { }, behaviourTree); // Empty action to prevent going to child too early base.behaviourTree = behaviourTree; }
public InverterDecoratorNode(string name, TreeNode child, BehaviourTreeEngine behaviourTree) { base.Child = child; Child.ParentNode = this; base.StateNode = new State(name, () => { }, behaviourTree); // Empty action to prevent errors base.behaviourTree = behaviourTree; }
private void CreateBehaviourTree() { behaviourTree = new BehaviourTreeEngine(false); rootSequence = behaviourTree.CreateSequenceNode("Root", false); selectorDoor = behaviourTree.CreateSelectorNode("Selector door"); sequenceDoor = behaviourTree.CreateSequenceNode("Sequence door", false); walkToDoor1 = behaviourTree.CreateLeafNode("Walk to door 1", WalkToDoor, ArriveToDoor); walkToDoor2 = behaviourTree.CreateLeafNode("Walk to door 2", WalkToDoor, ArriveToDoor); enterTheHouse = behaviourTree.CreateLeafNode("Enter the house", EnterTheHouse, HasEnteredTheHouse); openDoor1 = behaviourTree.CreateLeafNode("Open the door 1", OpenDoor, DoorOpened); openDoor2 = behaviourTree.CreateLeafNode("Open the door 2", OpenDoor, DoorOpened); unlockDoor = behaviourTree.CreateLeafNode("Find key", UnlockDoor, IsTheDoorUnlocked); smashDoor = behaviourTree.CreateLeafNode("Explode door", SmashDoor, DoorSmashed); rootSequence.AddChild(walkToDoor1); rootSequence.AddChild(selectorDoor); rootSequence.AddChild(enterTheHouse); selectorDoor.AddChild(openDoor1); selectorDoor.AddChild(sequenceDoor); selectorDoor.AddChild(smashDoor); sequenceDoor.AddChild(unlockDoor); sequenceDoor.AddChild(walkToDoor2); sequenceDoor.AddChild(openDoor2); behaviourTree.SetRootNode(rootSequence); }
public SelectorNode(string name, BehaviourTreeEngine behaviourTree) { this.childrenNodes = new List <TreeNode>(); this.childrenIndex = 0; base.HasSubmachine = false; base.behaviourTree = behaviourTree; base.StateNode = new State(name, () => { }, behaviourTree); // ACTION vacío para evitar errores }
//Acción de salida para árboles de comportamiento (sale a nodo hoja) con una acción a ejecutar y esperando a que el valor devuelto sea diferente de Running public UtilityAction(string name, Factor factor, Action ac, Func <ReturnValues> valueReturned, UtilitySystemEngine utilityCurvesEngine, BehaviourTreeEngine behaviourTreeEngine) { this.HasSubmachine = false; this.utilityState = new State(name, ac, utilityCurvesEngine); this.factor = factor; this.uCurvesEngine = utilityCurvesEngine; this.valueReturned = valueReturned; this.bt = behaviourTreeEngine; }
/// <summary> /// Runs the node infinite number of times /// </summary> /// <param name="name">The name of the node</param> /// <param name="child">The child of the node which will be executed</param> /// <param name="behaviourTree">The behaviour tree the node belongs to</param> public LoopDecoratorNode(string name, TreeNode child, BehaviourTreeEngine behaviourTree) { this.loopTimes = -1; this.timesLooped = 0; base.Child = child; Child.ParentNode = this; base.StateNode = new State(name, () => { }, behaviourTree); //Null action to prevent errors base.behaviourTree = behaviourTree; }
/// <summary> /// Runs the node a specific number of times /// </summary> /// <param name="name">The name of the node</param> /// <param name="child">The child of the node which will be executed</param> /// <param name="loopTimes">The number of times the node will execute the child</param> /// <param name="behaviourTree">The behaviour tree the node belongs to</param> public LoopDecoratorNode(string name, TreeNode child, int loopTimes, BehaviourTreeEngine behaviourTree) { this.loopTimes = loopTimes; this.timesLooped = 0; base.Child = child; Child.ParentNode = this; base.StateNode = new State(name, ToChild, behaviourTree); base.behaviourTree = behaviourTree; }
public TimerDecoratorNode(string name, TreeNode child, float time, BehaviourTreeEngine behaviourTree) { this.time = time; this.transitionLaunched = false; base.Child = child; Child.ParentNode = this; base.StateNode = new State(name, () => { }, behaviourTree); // Empty action to prevent going to child too early base.behaviourTree = behaviourTree; }
/// <summary> /// Creates a new <see cref="Transition"/> that exits from a Behaviour Tree to another Behaviour Tree. ONLY exits to Behaviour Trees /// </summary> /// <param name="transitionName">The name of the transition</param> /// <returns></returns> public Transition CreateExitTransition(string transitionName) { if (!transitions.ContainsKey(transitionName)) { BehaviourTreeEngine subBehaviourTree = this as BehaviourTreeEngine; Transition exitTransition = new Transition(transitionName, subBehaviourTree.GetRootNode(), NodeToReturn, NodeToReturn.StateNode.BehaviourEngine as BehaviourTreeEngine, subBehaviourTree); subBehaviourTree.GetRootNode().StateNode.BehaviourEngine.transitions.Add("Exit_Transition", exitTransition); return(exitTransition); } else { throw new DuplicateWaitObjectException(transitionName, "The transition already exists in the behaviour engine"); } }
public SequenceNode(string name, bool randomSequence, BehaviourTreeEngine behaviourTree) { this.childrenNodes = new List <TreeNode>(); this.childrenIndex = 0; this.randomSequence = randomSequence; base.HasSubmachine = false; base.behaviourTree = behaviourTree; base.StateNode = new State(name, () => { }, behaviourTree); // ACTION vacío para evitar errores // ¿BUG? Si se mete en FireNextNode en la transición, podría haber un error en cadena // Selector dentro de Sequence: nodo activo se queda en Selector y no en su hijo if (randomSequence) { RandomizeChildren(); } }
// Start is called before the first frame update private void Start() { behaviourTree = new BehaviourTreeEngine(BehaviourEngine.IsNotASubmachine); utilityCurves = new UtilitySystemEngine(BehaviourEngine.IsASubmachine); stateMachine = new StateMachineEngine(BehaviourEngine.IsASubmachine); recipe = GameObject.FindGameObjectWithTag("Recipe"); recipeAnimator = recipe.GetComponent <Animator>(); handler = transform.GetChild(5).gameObject; meshAgent = GetComponent <NavMeshAgent>(); pizzasCreated = 0; pepperoniCreated = 0; CreateStateMachine(); CreateUtilityCurves(); CreateBehaviourTree(); }
private void CreateBehaviourTree() { behaviourTree = new BehaviourTreeEngine(true); LeafNode toKey = behaviourTree.CreateLeafNode("To key", GoToKey, ArriveToKey); LeafNode getKey = behaviourTree.CreateLeafNode("Get key", GetKey, KeyTaken); LeafNode backToDoor = behaviourTree.CreateLeafNode("Back to door", ToDoor, ArriveToDoor); LeafNode openDoor = behaviourTree.CreateLeafNode("Open door", OpenDoor, DoorOpened); SequenceNode sequenceRoot = behaviourTree.CreateSequenceNode("Sequence root", false); sequenceRoot.AddChild(toKey); sequenceRoot.AddChild(getKey); sequenceRoot.AddChild(backToDoor); sequenceRoot.AddChild(openDoor); behaviourTree.SetRootNode(sequenceRoot); }
private void CreateBehaviourTree() { behaviourTree = new BehaviourTreeEngine(false); LeafNode toPoint1 = behaviourTree.CreateLeafNode("To point 1", () => ToPoint(routePoints[0]), () => ArrivedToPoint(routePoints[0])); LeafNode toPoint2 = behaviourTree.CreateLeafNode("To point 2", () => ToPoint(routePoints[1]), () => ArrivedToPoint(routePoints[1])); LeafNode toPoint3 = behaviourTree.CreateLeafNode("To point 3", () => ToPoint(routePoints[2]), () => ArrivedToPoint(routePoints[2])); LeafNode toPoint4 = behaviourTree.CreateLeafNode("To point 4", () => ToPoint(routePoints[3]), () => ArrivedToPoint(routePoints[3])); LeafNode toPoint5 = behaviourTree.CreateLeafNode("To point 5", () => ToPoint(routePoints[4]), () => ArrivedToPoint(routePoints[4])); LeafNode toPoint6 = behaviourTree.CreateLeafNode("To point 6", () => ToPoint(routePoints[5]), () => ArrivedToPoint(routePoints[5])); SequenceNode sequenceRoute = behaviourTree.CreateSequenceNode("Route", false); sequenceRoute.AddChild(toPoint1); sequenceRoute.AddChild(toPoint2); sequenceRoute.AddChild(toPoint3); sequenceRoute.AddChild(toPoint4); sequenceRoute.AddChild(toPoint5); sequenceRoute.AddChild(toPoint6); LoopDecoratorNode loopNode = behaviourTree.CreateLoopNode("Loop root", sequenceRoute); behaviourTree.SetRootNode(loopNode); }
private void CreateBehaviourTree() { behaviourTree = new BehaviourTreeEngine(false); LeafNode throwRod = behaviourTree.CreateLeafNode("Throw rod", ThrowRod, RodThrown); LeafNode catchSomething = behaviourTree.CreateLeafNode("Catch something", Catch, SomethingCatched); LeafNode returnToWater = behaviourTree.CreateLeafNode("Return to water", () => Invoke("ReturnToWater", 2), ReturnedToWater); LeafNode storeInBasket = behaviourTree.CreateLeafNode("Store in the basket", () => Invoke("StoreBasket", 2), StoredInBasket); TimerDecoratorNode timerNode = behaviourTree.CreateTimerNode("Timer node", catchSomething, 3); SelectorNode selectorNode = behaviourTree.CreateSelectorNode("Selector node"); selectorNode.AddChild(returnToWater); selectorNode.AddChild(storeInBasket); SequenceNode sequenceNode = behaviourTree.CreateSequenceNode("Sequence node", false); sequenceNode.AddChild(throwRod); sequenceNode.AddChild(timerNode); sequenceNode.AddChild(selectorNode); LoopDecoratorNode rootNode = behaviourTree.CreateLoopNode("Root node", sequenceNode); behaviourTree.SetRootNode(rootNode); }
/// <summary> /// Creates a new <see cref="Perception"/> of type <see cref="BehaviourTreeStatusPerception"/> /// </summary> /// <param name="behaviourTreeToCheck">The behaviour tree that will be checked</param> /// <param name="statusToReach">The status value that needs to reach to fire the transition</param> /// <returns></returns> public BehaviourTreeStatusPerception CreatePerception <PerceptionType>(BehaviourTreeEngine behaviourTreeToCheck, ReturnValues statusToReach) { return(new BehaviourTreeStatusPerception(behaviourTreeToCheck, statusToReach, this)); }
//Acción de salida para árboles de comportamiento (sale a nodo hoja instantáneamente) public UtilityAction(string name, Factor factor, ReturnValues valueReturned, UtilitySystemEngine utilityCurvesEngine, BehaviourTreeEngine behaviourTreeEngine) { this.HasSubmachine = false; Action action = () => { new Transition("Exit_Action_Transition", this.utilityState, new PushPerception(this.uCurvesEngine), this.uCurvesEngine.NodeToReturn, valueReturned, behaviourTreeEngine, this.uCurvesEngine) .FireTransition(); }; this.utilityState = new State(name, action, utilityCurvesEngine); this.factor = factor; this.uCurvesEngine = utilityCurvesEngine; }
/// <summary> /// Creates a transition between one <see cref="BehaviourEngine."/>, the submachine; and one <see cref="BehaviourTreeEngine"/>, the supermachine. /// </summary> /// <param name="name">The name of the transition</param> /// <param name="stateFrom">The exit state of the transition</param> /// <param name="perception">The perception that activates the transition</param> /// <param name="stateTo">The node where the Behaviour Tree is coming back</param> /// <param name="superMachine">The supermachine</param> /// <param name="subMachine">The submachine</param> public Transition(string name, State stateFrom, Perception perception, LeafNode stateTo, ReturnValues returnValue, BehaviourTreeEngine superMachine, BehaviourEngine subMachine) { this.Name = name; this.StateFrom = stateFrom; this.Perception = perception; this.StateTo = stateTo.StateNode; this.type = TRANSITION_TYPE.SUPER_TRANSITION; if (StateFrom.BehaviourEngine == superMachine) // Exits from the super-machine { this.BehaviourEngine = superMachine; Perception.SetBehaviourMachine(superMachine); superMachine.Configure(StateFrom) .OnExit(this.Name, () => Perception.Reset()) .InternalTransition(Perception, this.Name, () => ExitTransition(StateFrom, stateTo, returnValue, subMachine.GetState("Entry_Machine"), superMachine, subMachine)); } else // Exits from the sub-machine { this.BehaviourEngine = subMachine; Perception.SetBehaviourMachine(subMachine); subMachine.Configure(StateFrom) .OnExit(this.Name, () => Perception.Reset()) .InternalTransition(Perception, this.Name, () => ExitTransition(StateFrom, stateTo, returnValue, subMachine.GetState("Entry_Machine"), superMachine, subMachine)); } }
/// <summary> /// Executes the exit transitions between a submachine and the supermachine which is a <see cref="BehaviourTreeEngine"/> /// </summary> /// <param name="stateFrom">The exit state of the transition</param> /// <param name="stateTo">The entry state of the transition</param> /// <param name="entrySubMachineState">The 'Entry_State' of the submachine</param> /// <param name="superMachine">The supermachine where the trasition is going to</param> /// <param name="subMachine">The subsmachine the transition is leaving</param> private void ExitTransition(State stateFrom, LeafNode stateTo, ReturnValues returnValue, State entrySubMachineState, BehaviourTreeEngine superMachine, BehaviourEngine subMachine) { if (stateFrom.BehaviourEngine == superMachine) // Exits from the super-machine // Transitions from Submachine.CurrentState -> Submachine.EntryState { Transition returnTransition = new Transition("reset_submachine", subMachine.actualState, new PushPerception(subMachine), entrySubMachineState, subMachine); returnTransition.FireTransition(); subMachine.Reset(); subMachine.Active = false; superMachine.Active = true; stateTo.ReturnValue = returnValue; // Transitions from stateFrom -> stateTo // Maybe I should change this too, as I changed the next one? // TODO review if this is working properly Transition superTransition = new Transition("to_state", stateFrom, new PushPerception(superMachine), stateTo.StateNode, superMachine); superTransition.FireTransition(); } else // Exits from the sub-machine // Transitions from stateFrom -> Submachine.EntryState { Transition returnTransition = new Transition("reset_submachine", stateFrom, new PushPerception(subMachine), entrySubMachineState, subMachine); returnTransition.FireTransition(); subMachine.Reset(); subMachine.Active = false; superMachine.Active = true; stateTo.ReturnValue = returnValue; // Transitions from Supermachine.CurrentState -> stateTo /* ¿BUG? * stateTo SHOULD BE THE SAME AS SuperMachine.CurrentState --> We are exiting from a machine * that returns Succeed or Failed to the SuperMachine LeafNode, if we enter again to that Node * we are again putting the ReturnType to "process", so we enter in an infinite loop */ //Transition superTransition = new Transition("to_state", superMachine.actualState, new PushPerception(superMachine), stateTo.StateNode, superMachine); //superTransition.FireTransition(); } }
/// <summary> /// Creates a new specific <see cref="UtilityAction"/> in the utility curves engine that exits to the /// <see cref="LeafNode"/> that contains the <see cref="UtilitySystemEngine"/> when the function valueReturned /// returns something different than "Running". /// </summary> /// <param name="name">The name of the utility action</param> /// <param name="factor">The factor that will have the Utility Action</param> /// <param name="ac">The action that the <see cref="UtilityAction"/> will execute.</param> /// <param name="valueReturned">The <see cref="ReturnValues"/> returned to the <see cref="LeafNode"/>. It's used to wait for a /// "Succeed" or "Failed".</param> /// <param name="behaviourTreeEngine">The <see cref="BehaviourTreeEngine"/> that contains the <see cref="UtilitySystemEngine"/>.</param> public UtilityAction CreateUtilityAction(string name, Factor factor, Action ac, Func <ReturnValues> valueReturned, BehaviourTreeEngine behaviourTreeEngine) { if (!states.ContainsKey(name)) { UtilityAction uAction = new UtilityAction(name, factor, ac, valueReturned, this, behaviourTreeEngine); actions.Add(uAction); states.Add(name, uAction.utilityState); return(uAction); } else { throw new DuplicateWaitObjectException(name, "The utility action already exists in the utility engine"); } }
public ConditionalDecoratorNode(string name, TreeNode child, Perception condition, BehaviourTreeEngine behaviourTree) { this.conditionPerception = condition; base.Child = child; Child.ParentNode = this; base.StateNode = new State(name, () => { }, behaviourTree); // Empty action to prevent errors (going to child too early) base.behaviourTree = behaviourTree; }
public LeafNode(string name, Action action, Func <ReturnValues> succeedCondition, BehaviourTreeEngine behaviourTree) { this.succeedCondition = succeedCondition; this.nodeAction = action; base.HasSubmachine = false; base.StateNode = new State(name, NodeAction, behaviourTree); base.behaviourTree = behaviourTree; }
public BehaviourTreeStatusPerception(BehaviourTreeEngine behaviourTree, ReturnValues statusToReach, BehaviourEngine behaviourEngine) { this.behaviourTree = behaviourTree; this.BehaviourTreeStatus = statusToReach; this.behaviourEngine = behaviourEngine; }