Skip to main content
This demo shows how Edge conditions and loops work in the graph node system.

Run the Template

  1. Go to Assets/InworldRuntime/Scenes/Nodes and play the EdgeLoopDemo scene. EdgeLoop00
  2. Whenever you type something, it responds with the input prefixed by * characters on the left.
Edge

Understanding the Graph

NodeConnectionCanvas contains an InworldGraphExecutor. Loop01 The graph contains three nodes:
  • TextCombiner: A custom node that adds * in front of sentences.
  • NodeFinal: A custom conversation‑endpoint node that prints the text.
  • FilterInput: The start node, a custom node that filters out mismatched input types.
There are three edges:
  • FilterInput to TextCombiner
  • TextCombiner to FilterInput: This is a customized LoopEdge, with IsLoop toggled.
  • FilterInput to NodeFinal.
FilterInput is the StartNode and NodeFinal is the EndNode. EdgeNode01 You can also see this connection in the Graph Editor. It’s clearer. EdgeNode01

CustomNode details

TextCombiner

In its overridden ProcessBaseData(), it adds * to the left of the input text and sets it as the output.
TextCombinerNodeAsset.cs

FilterInput

This is a custom node used in the Character Interaction. It filters out input InworldBaseData that are neither InworldText nor InworldAudio.
FilterInputNodeAsset.cs

NodeFinal

NodeFinal uses the custom node ConversationEndpointNodeAsset. During CreateRuntime(), it stores the speaker’s name and later returns output text containing both the speaker’s name and the result. It is typically used as the end node in Character Interaction.
ConversationEndpointNodeAsset.cs

Edge

The loop edge from TextCombiner to FilterInput is a customized edge with IsLoop toggled. Loop04 In its overridden checking function MeetsCondition(): if the current loop count exceeds the limit, the edge blocks passage; otherwise, it allows passage (sending control back to the loop start FilterInput). Because each iteration prefixes another * before passing the result back to FilterInput, you will see the number of * increase with each loop.
Be mindful of memory allocation when using Loop Edges.Because the graph node system executes inside C++, each iteration may allocate new memory.
Other edges use the default behavior: they simply forward all output from the previous node to the next node.

InworldController

The InworldController contains no primitive modules.

Workflow

  1. When the game starts, InworldController initializes immediately because there are no primitives.
  2. Next, InworldGraphExecutor initializes its graph asset by calling each component’s CreateRuntime().
For how CreateRuntime works on custom nodes, see the CustomNode Demo. For edges, during CreateRuntime() the system calls SetEdgeCondition() and registers OnConditionCheck as the function pointer for the condition. Inside OnConditionCheck, the system calls the overridden MeetsCondition() virtual function implemented by each edge subclass.
InworldEdgeAsset.cs
  1. After initialization, the graph calls Compile() and returns the executor handle.
  2. After compilation, the OnGraphCompiled event is invoked.
In this demo, NodeConnectionTemplate subscribes to it and enables the UI components. Users can then interact with the graph system.
LoopEdgeNodeTemplate.cs
  1. After the UI is initialized, send the input text to the graph.
  2. Calling ExecuteGraphAsync() causes the graph to loop, sending the TextCombiner result back to FilterInput until the loop count configured by LoopEdge is reached.
It then produces a result and invokes OnGraphResult(), which NodeConnectionTemplate subscribes to in order to receive the data.
LoopEdgeNodeTemplate.cs