> ## Documentation Index
> Fetch the complete documentation index at: https://docs.inworld.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Overview

In the Unity AI Runtime, you can use the 3 following ways to interact with Inworld AI modals:

* Using the C# code to directly access the Primitive Modules.
* Generating a ScriptableObject GraphAsset, with the also generated EdgeAssets and NodeAssets that will interact with primitives automatically.
* Using the GraphViewEditor to automatically generate the graph system.

Apparently, using the GraphViewEditor should be the easiet.

Although in some case you will still need to directly modify the ScriptableObjects or even the Code.

For those part, we will introduce later.

In this tutorial, let's focus on creating graphs with GraphViewEditor.

## Life Cycle

For the graph/node system, the life cycle of the runtime (When you actually click the `Play` button) is like this:

<img src="https://mintcdn.com/inworldai/09jBaDxLDhFWSIuG/img/unity/framework/GraphLifeCycle.png?fit=max&auto=format&n=09jBaDxLDhFWSIuG&q=85&s=9e715f2b3107417b76020ae8aa056fce" alt="GraphLifeCycle" width="682" height="268" data-path="img/unity/framework/GraphLifeCycle.png" />

You will need a `InworldGraphExecutor` to hold the `GraphAsset`, it will do the above steps.

You will also need a `NodeTemplate` to communicate with the `InworldGraphExecutor`, to send and receive the data from Inworld.

<Steps titleSize="h3">
  <Step title="Clone a Scene">
    In this overview, let's focus on the graph creating, so we will use the current default GraphNodeTemplate in the demos.
    Let's clone a scene from `Assets/InworldRuntime/Scenes/Nodes/CharacterInteractionNode.unity`.

    Let's rename the cloned one whatever you want. i.e; `Demo`, and open it.

    <img src="https://mintcdn.com/inworldai/pDD5vvrZThONehMe/img/unity/framework/SceneClone.png?fit=max&auto=format&n=pDD5vvrZThONehMe&q=85&s=e56a86c6c851cd1e363b95afea155159" alt="SceneClone" width="1227" height="381" data-path="img/unity/framework/SceneClone.png" />
  </Step>

  <Step title="Check out the current Graph">
    The graph is held under the `InworldGraphExecutor`, which is at the root hierarchy of `CharacterInteractionCanvas`.

    Navigate to that place, double click the asset to open it in Inspector.

    <img src="https://mintcdn.com/inworldai/PEMIBdkx0YyDrDSz/img/unity/framework/CheckoutGraph01.png?fit=max&auto=format&n=PEMIBdkx0YyDrDSz&q=85&s=7f34e7d0ff4966a4197e2cd91f22e6ce" alt="CheckoutGraph01" width="1506" height="768" data-path="img/unity/framework/CheckoutGraph01.png" />

    Scroll down until you see the `Open Graph Editor` button. Click it.

    <img src="https://mintcdn.com/inworldai/PEMIBdkx0YyDrDSz/img/unity/framework/CheckoutGraph02.png?fit=max&auto=format&n=PEMIBdkx0YyDrDSz&q=85&s=d6054b1ec593626ed8730749e8a14834" alt="CheckoutGraph02" width="1068" height="600" data-path="img/unity/framework/CheckoutGraph02.png" />

    You'll see the graph in the editor, and you'll have a glimpse about how each node works together.

    <img src="https://mintcdn.com/inworldai/PEMIBdkx0YyDrDSz/img/unity/framework/CheckoutGraph03.png?fit=max&auto=format&n=PEMIBdkx0YyDrDSz&q=85&s=60f0f6696b73b4e9a69589851bbac095" alt="CheckoutGraph03" width="2511" height="852" data-path="img/unity/framework/CheckoutGraph03.png" />

    You can scroll the mouse wheel to zoom in and zoom out.

    You can press and hold the mouse wheel to move around.

    <img src="https://mintcdn.com/inworldai/4VuegDBaCnR73Uxj/img/unity/framework/Zoom.gif?s=42cf36189c93bbc5e39803a1eafe5436" alt="Zoom" width="1920" height="1080" data-path="img/unity/framework/Zoom.gif" />

    Let's not edit this graph to avoid polluting the demo. We will create our own later.
  </Step>

  <Step title="Create your own Graph Asset">
    <Steps>
      <Step title="Create Graph">
        Right click on the `Project` tab, select `Create > Inworld > Create Graph > CharacterInteraction`.

        <img src="https://mintcdn.com/inworldai/09jBaDxLDhFWSIuG/img/unity/framework/CreateGraph01.gif?s=5e632a3117c593df0da52f2e070a407d" alt="CreateGraph01" width="1920" height="1080" data-path="img/unity/framework/CreateGraph01.gif" />
      </Step>

      <Step title="Rename and save the asset." />

      <Step title="In the inspector, fill in the essential data. User data and character data are essential.">
        * User Data
        * Character Data (In Characters list of the Character Interaction Data).
        * Voice (If you're planning to use TTS)
        * Prompt (if you're planning to use LLM)
                  <img src="https://mintcdn.com/inworldai/09jBaDxLDhFWSIuG/img/unity/framework/CreateGraph02.png?fit=max&auto=format&n=09jBaDxLDhFWSIuG&q=85&s=abd77297d92da02096257c222ac9c2fd" alt="CreateGraph02" width="1425" height="779" data-path="img/unity/framework/CreateGraph02.png" />

        <Note>
          You can click the `◎` icon to select the default one first.

          Then clone and update your own data later.

          <img src="https://mintcdn.com/inworldai/09jBaDxLDhFWSIuG/img/unity/framework/CreateGraph03.png?fit=max&auto=format&n=09jBaDxLDhFWSIuG&q=85&s=8119ff37df5b7e1bcce1cae71081760f" alt="CreateGraph03" width="1208" height="284" data-path="img/unity/framework/CreateGraph03.png" />
        </Note>
      </Step>
    </Steps>
  </Step>

  <Step title="Edit your Graph">
    <Steps>
      <Step title="Open Graph Editor">
        Once the character data and the user data has been set, let's click the `Open in Graph Editor` button.

        <img src="https://mintcdn.com/inworldai/pDD5vvrZThONehMe/img/unity/framework/OpenEditor01.png?fit=max&auto=format&n=pDD5vvrZThONehMe&q=85&s=77e77206c4e81cee78522891759197e7" alt="OpenEditor01" width="1443" height="783" data-path="img/unity/framework/OpenEditor01.png" />
      </Step>

      <Step title="Create a FilterInputNode">
        Right click on the Graph Editor, select `Create Node > Custom Nodes... > FilterInputNode`.

        Rename it to `Input`.

        <Note>
          Each node has to be renamed and has a unique name after created.
          The graph compiler will fail if it found duplicated names.
        </Note>

        <img src="https://mintcdn.com/inworldai/pDD5vvrZThONehMe/img/unity/framework/OpenEditor02.gif?s=ed40fedde6b26040b5a1a25e8a404ed1" alt="OpenEditor02" width="1920" height="1080" data-path="img/unity/framework/OpenEditor02.gif" />

        The `FilterInputNode` is good to be use as the StartNode, because you can use it to receive multiple input nodes.

        For example, currently it will detect if the format of the inputting data is correct.

        If the Inputting data is `InworldText` or `InworldAudio`, it will pass, otherwise it will fail.

        <Note>
          Currently, this node only support `InworldText` and `InworldAudio`.
          But please feel free to inherit this `FilterInputNodeAsset` and add your desired input type on your own.
          (Still must be a existing child class of InworldBaseData though)
        </Note>
      </Step>

      <Step title="Create a STTNode">
        From the output of FilterInput, hold left mouse button, drag an edge out.

        Create a `STTNode` and rename it to `STT`.

        `STT(Speech-to-text) Node` is used to generate the text from player's audio input.

        It accepts `InworldAudio` as input, sends `InworldText` as output.

        <Tip>
          Did you notice that the background color of the STTNode is different?<br /><br />

          That's because it's a dll node, not a custom node.

          You probably don't want to inherit a dll node, because if you do, the graph system may get broken.
        </Tip>
      </Step>

      <Step title="Create a AddSpeechEventNode">
        Right click on the Graph Editor, select `Create Node > Custom Nodes... > AddSpeechEventNode`.

        Rename it to be `PlayerSpeech`.

        Set the `IsPlayer` to be `true`.

        The `AddSpeechEventNode` basically converts everything to `InworldText`.

        Meanwhile, it will store this piece of data in the `ConversationData` of the `PromptAsset`, which will later be used to generate the prompt.

        <img src="https://mintcdn.com/inworldai/PEMIBdkx0YyDrDSz/img/unity/framework/AddSpeech.png?fit=max&auto=format&n=PEMIBdkx0YyDrDSz&q=85&s=2730b45b50241e6248cb81347731f488" alt="AddSpeech" width="2559" height="855" data-path="img/unity/framework/AddSpeech.png" />

        <Note>
          It's expected to have a pair of AddSpeechEventNode, one for player, one for agent.

          By setting the `IsPlayer` to be true, the generated data will be set into the prompt as the `Player's speech`.

          If not set, the agent will get confused with its identity.
        </Note>
      </Step>

      <Step title="Connect Nodes">
        Connect `Input` to `STT`, `STT` to `PlayerSpeech`, and `Input` to `PlayerSpeech`.\\

        <img src="https://mintcdn.com/inworldai/pDD5vvrZThONehMe/img/unity/framework/PlayerSpeech.gif?s=722a90f7a7e67326e2b1a3c5a365d1a6" alt="PlayerSpeech" width="1920" height="1080" data-path="img/unity/framework/PlayerSpeech.gif" />
      </Step>

      <Step title="Change Edge Types">
        Right click the edge from `Input` to `STT`, select `Set Edge Type > Audio`.

        Right click the edge from `Input` to `PlayerSpeech`, select `Set Edge Type > Text`.

        <img src="https://mintcdn.com/inworldai/pDD5vvrZThONehMe/img/unity/framework/SetEdgeType.gif?s=8aae6bb83c9faa529ebdac0e06ccbcb4" alt="SetEdgeType" width="1920" height="1080" data-path="img/unity/framework/SetEdgeType.gif" />

        <Warning>
          By default, the edge can pass through everything without checking.<br />
          But each node can only receive certain amount of data types as their input.<br />
          Data type mismatch may even lead the Unity Editor to **crash**!<br />
          So it's necessary to set data type for the edges to mark specific data transfer.
        </Warning>
      </Step>

      <Step title="Connect to FormatPromptNode">
        Extend `PlayerSpeech` node out to create a `FormatPromptNode`

        The `FormatPromptNode` is a customNode. It converts `InworldText` to `LLMChatRequest`, that will be used in `LLMNode` as input.

        The `FormatPromptNode` will use the current graph's prompt data. Set under the `InworldGraphAsset` you just filled.

        <img src="https://mintcdn.com/inworldai/pDD5vvrZThONehMe/img/unity/framework/Prompt01.png?fit=max&auto=format&n=pDD5vvrZThONehMe&q=85&s=9e4c23f18204368e8a84678e99e655e8" alt="Prompt01" width="1173" height="786" data-path="img/unity/framework/Prompt01.png" />

        If you double click to open it, you'll find 2 fields. `Prompt` and `JinjaPrompt`.

        We will use jinja to take the previous node's output, `InworldText`, together with the previously filled `UserData`, `CharacterData` to replace those `{{}}` defined the `Prompt` to generate the `JinjaPrompt` as the result.

        <img src="https://mintcdn.com/inworldai/pDD5vvrZThONehMe/img/unity/framework/Prompt03.png?fit=max&auto=format&n=pDD5vvrZThONehMe&q=85&s=2a8524bc3a57784ab9a33e008051ce8e" alt="Prompt03" width="1236" height="1008" data-path="img/unity/framework/Prompt03.png" />

        And the `JinjaPrompt`, is the actual data we are going to send to `LLMNode`
      </Step>

      <Step title="Connect to LLMNode">
        Extend `FormatPromptNode` node out to create a `LLMNode`.

        The LLMNode is a dll node that cannot be inherrited.

        It takes `LLMChatRequest` as input, returns `LLMChatResponse` as output.
      </Step>

      <Step title="Create another AddSpeechEventNode for Character">
        Extend `LLMNode` node out to create another `AddSpeechEventNode`.

        Rename it to be `CharacterSpeech`.

        Set the `IsPlayer` to be `false`.
      </Step>

      <Step title="Connect to TTSNode">
        Extend `CharacterSpeech` node out to create a `TTSNode`.

        Rename it to be `TTS`.

        Set the voice to be an available voiceID (Default is not an available ID right now. Please rename a valid voiceID)

        <img src="https://mintcdn.com/inworldai/pDD5vvrZThONehMe/img/unity/framework/PromptToTTS.gif?s=98c969d3d62ad6d671fd1ad5f9c451d2" alt="PromptToTTS" width="1920" height="1080" data-path="img/unity/framework/PromptToTTS.gif" />

        Done!

        You've finally finished a basic character conversation graph, with `InworldText` and `InworldAudio` as input, `InworldAudio` as output.

        It will take your typed or spoken speech as input, use STT to convert your audio into text, pasted in the current prompt, get the response, then speak out with TTS.
      </Step>

      <Step title="Save your graph">
        You can simply press `Ctrl + S` or press the `Save button` at the top to save this graph.

        <img src="https://mintcdn.com/inworldai/pDD5vvrZThONehMe/img/unity/framework/SaveGraph.png?fit=max&auto=format&n=pDD5vvrZThONehMe&q=85&s=4503f9850f60825c6a746c9c2879b23a" alt="SaveGraph" width="2538" height="642" data-path="img/unity/framework/SaveGraph.png" />

        After saved, you will find all the related NodeAssets and EdgeAssets are already created.

        And all the Start/End Nodes are set.

        Those ScriptableObjects are stored by default under the folder `Asset/Data/{GraphName}`

        <img src="https://mintcdn.com/inworldai/pDD5vvrZThONehMe/img/unity/framework/SaveGraph02.png?fit=max&auto=format&n=pDD5vvrZThONehMe&q=85&s=85a27640f511a4f810787779f1656beb" alt="SaveGraph02" width="1310" height="981" data-path="img/unity/framework/SaveGraph02.png" />
      </Step>
    </Steps>
  </Step>

  <Step title="Test your Graph">
    <Steps>
      <Step title="Apply your graph">
        Find the `InworldGraphExecutor`, by default it's at the `CharacterInteractionCanvas`.

        Replace the graph asset with the one you just created.

        <img src="https://mintcdn.com/inworldai/PEMIBdkx0YyDrDSz/img/unity/framework/ChangeGraph01.png?fit=max&auto=format&n=PEMIBdkx0YyDrDSz&q=85&s=4f5b682ed48121c27fd3f20a1593e297" alt="ChangeGraph01" width="1368" height="761" data-path="img/unity/framework/ChangeGraph01.png" />
      </Step>

      <Step title="Run in editor">
        <iframe style={{ aspectRatio: '16 / 9', width: '100%', height: 'auto' }} src="https://drive.google.com/file/d/1necnwYgaLE-iMVZSdBner6pOSvTLCJ3k/preview" title="Unity AI Runtime - Build your own Sample 01" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowFullScreen />

        You will find generally it's working, just there are not bubbles popping out.

        That's because we only have 1 end node, that's a TTSNode, so only the TTSOutput will be send out during the graph execution.
      </Step>
    </Steps>
  </Step>

  <Step title="Update your Graph">
    <Steps>
      <Step title="Add ConversationEndpointNodes">
        Open your graph editor, adding `ConversationEndpointNode` right after each `AddSpeechEventNode` (CharacterSpeech and PlayerSpeech)

        The `ConversationEndpointNodes` is a customNode that often used as EndNodes, it will generate the sentence like `{Speaker}: {Contents}`.

        For the user to extract and render correspondently.
      </Step>

      <Step title="Rename ConversationEndpointNodes">
        * Rename the one after `CharacterSpeech` to `CharacterFinal` and set the `IsPlayer` to be `false`.
        * Rename the one after `PlayerSpeech` to `PlayerFinal` and set the `IsPlayer` to be `true`.
                  <img src="https://mintcdn.com/inworldai/09jBaDxLDhFWSIuG/img/unity/framework/EditGraph.gif?s=c8bc9d1429ca444cb716413995e60c0f" alt="EditGraph" width="1920" height="1080" data-path="img/unity/framework/EditGraph.gif" />
      </Step>

      <Step title="Save the graph">
        Press "Save", you will see the data of the `GraphAsset` has changed.

        The `EndNodes` now contains 3 nodes.\\

        <img src="https://mintcdn.com/inworldai/09jBaDxLDhFWSIuG/img/unity/framework/EditGraph02.png?fit=max&auto=format&n=09jBaDxLDhFWSIuG&q=85&s=044c3ccdd29039ab25fa778e204bfdd6" alt="EditGraph02" width="1374" height="663" data-path="img/unity/framework/EditGraph02.png" />
      </Step>

      <Step title="Run in editor">
        <iframe style={{ aspectRatio: '16 / 9', width: '100%', height: 'auto' }} src="https://drive.google.com/file/d/19kjookfOBtJryFHKQye7cDoQ6lR-NRJw/preview" title="Unity AI Runtime - Build your own Sample 02" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowFullScreen />

        Done!
        You will find generally it's working, and the bubbles are also popped out!
      </Step>
    </Steps>
  </Step>
</Steps>
