While the recommended way of working with NodeCanvas is to create Tasks and use them instead so that the design can be modular, you are also able to create your own custom Behaviour Tree nodes, either Composites, Decorators or Leafs. In either case, you have to derive from the respective base type, override the required methods and use the inherited properties.
Following is a template with most methods that you can optionally override and are common to all three behaviour tree node types.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
using UnityEngine; using NodeCanvas.Framework; using ParadoxNotion.Design; namespace NodeCanvas.BehaviourTrees{ [Category("My Nodes")] [Icon("SomeIcon")] [Description("Some description")] public class NodeName : BTNode { //When the BT starts public override void OnGraphStarted(){ } //When the BT stops public override void OnGraphStoped(){ } //When the BT pauses public override void OnGraphPaused(){ } //When the node is Ticked protected override Status OnExecute(Component agent, IBlackboard blackboard){ return Status.Success; } //When the node resets (start of graph, interrupted, new tree traversal). protected override void OnReset(){ } #if UNITY_EDITOR //This GUI is shown IN the node IF you want protected override void OnNodeGUI(){ } //This GUI is shown when the node is selected IF you want protected override void OnNodeInspectorGUI(){ DrawDefaultInspector(); //this is done when you dont override this method anyway. } #endif } } |
Here are some important common inherited properties:
Status status
The current status of the node. You can also use this to temporarily store a status as you’ll see later on.
Component graphAgent
The executive agent of the Behaviour Tree
IBlackboard graphBlackboard
The blackboard of the Behaviour Tree
List<Connection> outConnections
In NodeCanvas, connections are object by themselves. You get to access child nodes through their connections. Connections also have an Execute method which returns a Status as you will see later on.
Behaviour Tree leaf nodes, have no child nodes. To create a leaf node derive from BTNode. Following is a simple delay Behaviour Tree action node.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
using UnityEngine; using NodeCanvas.Framework; using ParadoxNotion.Design; namespace NodeCanvas.BehaviourTrees{ [Category("My Nodes")] [Icon("SomeIcon")] [Description("Wait for an ammount of seconds then return Success")] public class SimpleDelay : BTNode { public BBParameter<float> waitTime; private float timer; protected override Status OnExecute(Component agent, IBlackboard blackboard){ timer += Time.deltaTime; if (timer > waitTime.value) return Status.Success; return Status.Running; } protected override void OnReset(){ timer = 0; } } } |
Again, it is very recommended to use the existing Action and Condition Behaviour Tree nodes and create Action and Condition Tasks respectively to use with them instead of creating leaf action/condition nodes this way.
To create a Decorator you should derive from BTDecorator base type. Decorator nodes can only have one child node. You access that child through the connection object. Here is an Inverter Decorator for example.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
using UnityEngine; using NodeCanvas.Framework; using ParadoxNotion.Design; namespace NodeCanvas.BehaviourTrees{ [Category("Decorators")] [Icon("SomeIcon")] [Description("Invert Success to Failure and Failure to Success")] public class Inverter : BTDecorator{ protected override Status OnExecute(Component agent, IBlackboard blackboard){ status = decoratedConnection.Execute(agent, blackboard); if (status == Status.Success) return Status.Failure; if (status == Status.Failure) return Status.Success; return status; } } } |
You get to access and execute the decorated child node through the connection object. In NodeCanvas, connections are objects by themselves and they also have an Execute method that returns a Status.
To create a Composite, you derive from BTComposite base type. Composite nodes can have any number of connected child nodes. Similar to decorators, you get to access and execute child nodes through the connections. Here is an example of a simple sequencer.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
using UnityEngine; using NodeCanvas.Framework; using ParadoxNotion.Design; namespace NodeCanvas.BehaviourTrees{ [Category("Composites")] [Icon("Sequencer")] [Description("Execute the child nodes in order from left to right")] public class SimpleSequencer : BTComposite { private int lastRunningNodeIndex; protected override Status OnExecute(Component agent, IBlackboard blackboard){ for (int i = lastRunningNodeIndex; i < outConnections.Count; i++){ status = outConnections[ i ].Execute(); if (status == Status.Running){ lastRunningNodeIndex = i; return Status.Running; } if (status == Status.Failure) return Status.Failure; } return Status.Success; } protected override void OnReset(){ lastRunningNodeIndex = 0; } } } |
That’s it. Remember that double clicking on a node, opens it up in your IDE.
© Paradox Notion 2014-2024. All rights reserved.