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

# Game Engines (Unity, Godot)

> Give a game character a voice: it listens through the microphone, answers in its own voice from where it stands, moves its mouth, and calls your game functions

<Note>
  Preview. The Unity package and the Godot addon are new; tell us what your game needs at [contact@lokutor.com](mailto:contact@lokutor.com).
</Note>

Add a **Lokutor Agent** to any character and it becomes a voice agent:

* it **listens** through the player's microphone (the server notices when the player stops talking),
* **answers in its own voice** from where it stands in the world (3D audio),
* **moves its mouth** with what it says (blend shape, jaw bone, or a 0..1 value for anything else),
* and **calls your game's functions** when the conversation calls for it: sell an item, open a gate,
  start a quest. These are [tool calls](/sdk/tool-calling), set up as "actions".

## Install

<Tabs>
  <Tab title="Unity">
    Unity 2021.3 or newer, no other packages. **Window > Package Manager > + > Add package from git URL**:

    ```
    https://github.com/lokutor-ai/lokutor-sdk.git?path=/unity
    ```
  </Tab>

  <Tab title="Godot">
    Godot 4.3 or newer, pure GDScript. Copy
    [`godot/addons/lokutor`](https://github.com/lokutor-ai/lokutor-sdk/tree/main/godot/addons/lokutor)
    into your project's `addons/` folder, then **Project > Project Settings > Plugins > Lokutor Voice Agents >
    Enable**. Enabling it turns on **Audio > Driver > Enable Input**, which the microphone needs.
  </Tab>
</Tabs>

## Your first talking character

<Steps>
  <Step title="Add the agent">
    **Unity:** select the character, **Add Component > Lokutor > Lokutor Agent**.
    **Godot:** add a **LokutorAgent** child node (put it at the head: the voice comes from there).
  </Step>

  <Step title="Paste your API key">
    From [app.lokutor.com](https://app.lokutor.com). Fine while prototyping; see [Shipping](#shipping-keep-the-key-on-your-server) before you release.
  </Step>

  <Step title="Describe the character">
    Write who it is in **Persona**, and pick a **Voice** (`F1`-`F5`, `M1`-`M5`, or a voice from
    [Voices](/voices-languages-models)) and **Language**.
  </Step>

  <Step title="Press Play and talk">
    The character greets the player and listens. Headphones recommended.
  </Step>
</Steps>

To use an agent built in the dashboard (prompt, voice, knowledge, tools), set **Agent Id** and leave
Persona, Voice and Language empty.

## Let the character do things

Actions are game functions the character can call. Without code, wire them in the editor: Unity's
**Game actions** list (a name, when to use it, and an **On Called** event) or Godot's **Game Actions**
(`LokutorAction`: a name, when to use it, a target node and method). With arguments, register them in
code. The handler runs on the main thread and returns a sentence that tells the character what happened:

<CodeGroup>
  ```csharp Unity theme={null}
  using Lokutor;

  var shopkeeper = GetComponent<LokutorAgent>();
  shopkeeper.AddAction("give_item", "Sell an item to the player", args =>
  {
      string item = args.GetString("item");
      inventory.Add(item);
      gold -= prices[item];
      return $"Gave the {item}. The player has {gold} gold left.";
  }, new ActionParam("item", "Which item", ParamType.String, true, "iron sword", "healing potion"));
  ```

  ```gdscript Godot theme={null}
  @onready var shopkeeper: LokutorAgent = $Shopkeeper/Head/LokutorAgent

  func _ready():
      shopkeeper.add_action("give_item", "Sell an item to the player", _give_item,
          {"item": {"type": "string", "description": "Which item", "enum": ["iron sword", "healing potion"]}})

  func _give_item(args: Dictionary) -> String:
      inventory.append(args.item)
      return "Gave the %s." % args.item
  ```
</CodeGroup>

## Events and control

<CodeGroup>
  ```csharp Unity theme={null}
  agent.onPlayerSaid.AddListener(text => subtitles.ShowPlayer(text));
  agent.onCharacterSaid.AddListener(text => subtitles.ShowNpc(text));
  agent.onStateChanged.AddListener(state => thinkingBubble.SetActive(state == AgentState.Thinking));

  agent.StartConversation();   // e.g. when the player walks up (turn off Start On Awake)
  agent.StopConversation();    // when they walk away
  agent.SetPersona("You are now angry with the player.");
  ```

  ```gdscript Godot theme={null}
  shopkeeper.character_said.connect(func(text): $Subtitles.text = text)
  shopkeeper.state_changed.connect(_on_state)   # DISCONNECTED, CONNECTING, READY, PLAYER_TALKING, THINKING, SPEAKING

  shopkeeper.start_conversation()   # e.g. when the player walks up (turn off Start On Ready)
  shopkeeper.stop_conversation()    # when they leave
  shopkeeper.set_persona("You are now angry with the player.")
  ```
</CodeGroup>

A conversation is billed as agent minutes while it is connected, like any other session: start it when
the player engages and stop it when they leave.

## Microphone and echo

* **Always** (default): the microphone is open; the server detects turns.
* **Push to talk**: hold a key or input action, or call `SetTalking(true)` / `set_talking(true)` from your
  own input code.
* **Mute mic while speaking** (on by default) sends silence while the character's voice can still be
  heard, through the engine's buffers and the room's echo, so laptop speakers cannot make it answer itself.
  Turn it off when players wear headphones, so they can interrupt the character.

## Shipping: keep the key on your server

An API key inside a game build can be extracted. For a release, let your backend trade the key for a
short-lived ticket ([`POST /ws-ticket`](/guides/secure-browser-setup)) and give the agent that:

<CodeGroup>
  ```csharp Unity theme={null}
  agent.TicketProvider = async () => await myBackend.GetLokutorTicketAsync();
  ```

  ```gdscript Godot theme={null}
  shopkeeper.ticket_provider = func(): return await my_backend.get_lokutor_ticket()
  ```
</CodeGroup>

## Platforms

| | Unity | Godot |
| :- | :- | :- |
| Windows, macOS, Linux | Yes | Yes |
| Android, iOS | Yes (add a microphone usage description) | Yes (microphone permission in the export preset) |
| Web | Not yet: use the [JavaScript SDK](/guides/browser-setup) | Not tested yet |

## Examples

The [`godot/`](https://github.com/lokutor-ai/lokutor-sdk/tree/main/godot) folder is a Godot project: press
Play to talk to **Brom**, a blacksmith who sells you a sword through an action. Unity's Package Manager
has a **Talking blacksmith** sample: add its script to an empty GameObject and press Play.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.