Skip to main content
Version: 🚧 Work in Progress

Concepts

There are many unique concepts and ideas that are essential to understanding Jungle. This page will help you understand these core concepts and ideas.


Important Terms​

  • Tree: Collection of nodes connected together to form sequences.
  • Node: Unit of logic/behavior that performs a specific task.
  • Port: Connection point on a node where calls are sent or received.
  • Edge: Link between an input port and output port.
  • Call: Payload of data sent from an output port to an input port.

Node Variants​

Jungle has four node variants builtin. Each node variant has a unique purpose and use case. Understanding the differences between each node variant is essential to creating custom nodes.

Branch Node​

One input port and multiple output ports. It is used for conditional logic and branching behavior.

IO Node​

One input port and one output port. It is designed for simple logic and behavior. The "IO" stands for Input/Output.

Identity Node​

One input port and one output port. Its port types are automatically defined based on the nodes connected to it. This makes it flexible and useful for nodes like "Wait for Seconds," which don’t need predefined inputs to function.

Event Node​

No input ports and one or more output ports. It is used for event-driven logic and starts automatically when the tree is played.


Lifecycles​

Both trees and nodes follow a lifecycle managed by Jungle's runtime. Understanding the lifecycle will help you to better understand the process of creating and managing trees and nodes.

Trees​

▢️ On Played:​

  • All event nodes in the tree are started.
    • For example, the start node is an event node started when the tree is played.

πŸ”„ While Running:​

  • The tree automatically manages and updates running nodes.
Automatic Stopping

The tree will automatically stop when no nodes are running.

πŸ›‘ On Stopped:​

  • All running nodes (if any) are stopped.
  • All created revert actions (if any) are called.

Nodes​

▢️ On Started:​

  • The OnStart method is called on the node.
Immediately Stopping Node

If the Stop or CallAndStop method is called from the OnStart method, the OnUpdate, OnLateUpdate, and OnFixedUpdate methods will not be called by the runtime.

πŸ”„ While Running:​

  • The OnUpdate, OnLateUpdate, and OnFixedUpdate methods are called on the node.

πŸ›‘ On Stopped:​

  • The OnStop method is called on the node.

Port Calls​

Nodes use ports to send and receive data. Ports are linked by edges, which connect an output port on one node to an input port on another. Port calls always flow from an output port to an input port.

When a node makes a port call, it's sent from one of its output ports. The call then flows through the edge into the input ports of all nodes connected to the output port. Port calls can contain a value (called a payload) that can be used as an input for nodes.

The syntax for port calls is slightly different for each node variation, but the concept remains the same. To send a port call, you can use either the Call or CallAndStop method on the current node:

  • Call: Sends a port call to all connected nodes and lets the current node continue running.
  • CallAndStop: Sends a port call to all connected nodes and stops the current node.

Below are examples for making port calls for each node variant.


Branch Node​

Branch nodes have multiple output ports, so you must specify the output port index when making a port call. The output port index is the index of the output port you want to call, starting from 0.

The Branch node Call and CallAndStop methods can take an array of Port.Call or a single Port.Call. Ensure the payload type matches the type of its respective output port.

In this BranchNode example, the node has two output ports.

  • Output port one has an output type of integer, so the payload for calls on that port must be of type int.
  • Output port two has an output type of string, so the payload for calls on that port must be of type string.
using Jungle;

[BranchNode(
OutputPortNames = new[]
{
// ↓↓↓↓↓↓↓↓ Output port 1 name
"Output 1",
// ↓↓↓↓↓↓↓↓ Output port 2 name
"Output 2"
},
OutputPortTypes = new[]
{
// ↓↓↓ Output port 1 type
typeof(int),
// ↓↓↓↓↓↓ Output port 2 type
typeof(string)
}
)]
public class MyBranchNode : BranchNode<int>
...

BranchNode.Call(Port.Call[])​

This example makes calls to both output ports and the node continues running.

Call(new []
{
// Port Index ↓ ↓ Payload
new Port.Call(0, 1),
// Port Index ↓ ↓↓↓↓↓↓↓↓↓↓↓↓↓ Payload
new Port.Call(1, "Hello, World!")
});

BranchNode.Call(Port.Call)​

This example makes individual calls to both output ports and the node continues running.

//      Port Index ↓  ↓ Payload
Call(new Port.Call(0, 1));
//      Port Index ↓   ↓↓↓↓↓↓↓↓↓↓↓↓↓ Payload
Call(new Port.Call(1, "Hello, World!"));

BranchNode.CallAndStop(Port.Call[])​

This example makes calls to both output ports and the node stops running.

CallAndStop(new []
{
// Port Index ↓ ↓ Payload
new Port.Call(0, 1),
// Port Index ↓ ↓↓↓↓↓↓↓↓↓↓↓↓↓ Payload
new Port.Call(1, "Hello, World!")
});

BranchNode.CallAndStop(Port.Call)​

This example makes individual calls to both output ports and the node stops running.

//             Port Index ↓  ↓ Payload
CallAndStop(new Port.Call(0, 1));
//             Port Index ↓   ↓↓↓↓↓↓↓↓↓↓↓↓↓ Payload
CallAndStop(new Port.Call(1, "Hello, World!"));

IO Node​

IO nodes have only one output port, so you do not need to specify the output port index when making a port call. Because requiring a developer to always specify the first output port index would be redundant, the Port.Call object is not used.

The IO node Call and CallAndStop methods take a payload and do not require an output port index. Make sure the type of the payload matches the type of the output port.

In this IONode example, the node has one output port.

  • The output port has an output type of integer, so the payload for calls on that port must be of type int.
using Jungle;

[IONode(
// ↓↓↓↓↓↓ Output port name
OutputPortName = "Output",
// ↓↓↓ Output port type
OutputPortType = typeof(int)
)]
public class MyIONode : IONode<int>
...

IONode.Call(object)​

This example makes a call to the output port and the node continues running.

//   ↓ Payload
Call(1);

IONode.CallAndStop(object)​

This example makes a call to the output port and the node stops running.

//          ↓ Payload
CallAndStop(1);

Identity Node​

Identity nodes do not allow you to directly interact with the inputted and outputted payload. Port calls are made using either the Call or CallAndStop methods without any arguments.

In this IdentityNode example, the node has one output port that's set by the nodes input type.

using Jungle;

public class MyIdentityNode : IdentityNode
...

IdentityNode.Call()​

This example makes a call to the output port and the node continues running.

Call();

IdentityNode.CallAndStop()​

This example makes a call to the output port and the node stops running.

CallAndStop();

Event Node​

Event nodes have one or multiple output ports, so you must specify the output port index when making a port call. The output port index is the index of the output port you want to call, starting from 0.

The Event node Call and CallAndStop methods can take an array of Port.Call or a single Port.Call. Make sure the type of the payload matches the type of the output port.

In this EventNode example, the node has two output ports.

  • Output port one has an output type of integer, so the payload for calls on that port must be of type int.
  • Output port two has an output type of string, so the payload for calls on that port must be of type string.
using Jungle;

[EventNode(
OutputPortNames = new[]
{
// ↓↓↓↓↓↓↓↓ Output port 1 name
"Output 1",
// ↓↓↓↓↓↓↓↓ Output port 2 name
"Output 2"
},
OutputPortTypes = new[]
{
// ↓↓↓ Output port 1 type
typeof(int),
// ↓↓↓↓↓↓ Output port 2 type
typeof(string)
}
)]
public class MyEventNode : EventNode
...

EventNode.Call(Port.Call[])​

This example makes calls to both output ports and the node continues running.

Call(new []
{
// Port Index ↓ ↓ Payload
new Port.Call(0, 1),
// Port Index ↓ ↓↓↓↓↓↓↓↓↓↓↓↓↓ Payload
new Port.Call(1, "Hello, World!")
});

EventNode.Call(Port.Call)​

This example makes individual calls to both output ports and the node continues running.

//      Port Index ↓  ↓ Payload
Call(new Port.Call(0, 1));
//      Port Index ↓   ↓↓↓↓↓↓↓↓↓↓↓↓↓ Payload
Call(new Port.Call(1, "Hello, World!"));

EventNode.CallAndStop(Port.Call[])​

This example makes calls to both output ports and the node stops running.

CallAndStop(new []
{
// Port Index ↓ ↓ Payload
new Port.Call(0, 1),
// Port Index ↓ ↓↓↓↓↓↓↓↓↓↓↓↓↓ Payload
new Port.Call(1, "Hello, World!")
});

EventNode.CallAndStop(Port.Call)​

This example makes individual calls to both output ports and the node stops running.

//             Port Index ↓  ↓ Payload
CallAndStop(new Port.Call(0, 1));
//             Port Index ↓   ↓↓↓↓↓↓↓↓↓↓↓↓↓ Payload
CallAndStop(new Port.Call(1, "Hello, World!"));