Unity SDK
Add NPC conversations to your Unity game with the Foil Engine UPM package.
Installation
Install via Unity Package Manager using a git URL. In Unity, go to Window → Package Manager → + → Add package from git URL and enter:
https://github.com/py1218/foilengine-unity.git💡Tip
Requires Unity 2021.3 or later. The SDK depends on Newtonsoft.Json (included with Unity 2020+).
Quick Start (Async/Await)
Unity 2023+ supports async/await natively:
using FoilEngine;
using FoilEngine.Models;
var client = new FoilEngineClient("pk_live_...");
// Discover your personas
Persona[] personas = await client.Personas.ListAsync();
Debug.Log(personas[0].Name); // "Grumpy Barista"
// Initialize a session
SessionInit session = await client.Chat.InitSessionAsync(
personaId: personas[0].Id,
userSessionId: "player-001",
playerName: "Alex",
playerGender: "non-binary"
);
Debug.Log(session.Message); // NPC's greeting
// Send a message
ChatResponse response = await client.Chat.SendMessageAsync(
personaId: personas[0].Id,
message: "What do you recommend?",
userSessionId: "player-001"
);
Debug.Log(response.Message); // NPC's reply
Debug.Log(response.CurrentState); // State machine state
Debug.Log(response.Score); // Session scoreQuick Start (Coroutines)
For Unity 2021–2022 or if you prefer coroutines:
using UnityEngine;
using FoilEngine;
using FoilEngine.Models;
public class NPCManager : MonoBehaviour
{
private FoilEngineClient client;
void Start()
{
client = new FoilEngineClient("pk_live_...");
StartCoroutine(client.Personas.List(
onSuccess: personas => {
Debug.Log(personas[0].Name);
StartCoroutine(InitChat(personas[0].Id));
},
onError: err => Debug.LogError(err.Message)
));
}
IEnumerator InitChat(string personaId)
{
yield return client.Chat.InitSession(
personaId: personaId,
userSessionId: "player-001",
playerName: "Alex",
playerGender: "non-binary",
onSuccess: session => Debug.Log(session.Message),
onError: err => Debug.LogError(err.Message)
);
}
}Configuration
var client = new FoilEngineClient(
apiKey: "pk_live_...", // required
baseUrl: "http://localhost:8000", // default: https://api.foilengine.io
timeoutSeconds: 30, // default: 30
maxRetries: 3 // default: 3
);Available Methods
Personas
| Async | Coroutine | Description |
|---|---|---|
client.Personas.ListAsync() | client.Personas.List(onSuccess, onError) | List all published personas |
Machines
| Async | Coroutine | Description |
|---|---|---|
client.Machines.ListAsync(personaId, userSessionId) | client.Machines.List(personaId, userSessionId, onSuccess, onError) | List available machines for a player |
Chat
| Async | Coroutine | Description |
|---|---|---|
InitSessionAsync(...) | InitSession(..., onSuccess, onError) | Start a new conversation |
SendMessageAsync(...) | SendMessage(..., onSuccess, onError) | Send a message, get NPC reply |
GetSessionAsync(...) | GetSession(..., onSuccess, onError) | Check if a session exists |
GetHistoryAsync(...) | GetHistory(..., onSuccess, onError) | Get full message history |
ResetAsync(...) | Reset(..., onSuccess, onError) | Delete a session |
Error Handling
Async/Await
using FoilEngine;
try
{
var session = await client.Chat.GetSessionAsync(personaId, "player-001");
}
catch (NotFoundException)
{
// No existing session — initialize one
var session = await client.Chat.InitSessionAsync(personaId, "player-001", "Alex", "non-binary");
}
catch (RateLimitException e)
{
Debug.Log($"Retry after {e.RetryAfter}s");
}
catch (AuthenticationException)
{
Debug.LogError("Invalid API key");
}Coroutines
StartCoroutine(client.Chat.GetSession(
personaId: personaId,
userSessionId: "player-001",
onSuccess: session => Debug.Log(session.Exists),
onError: err => {
if (err is NotFoundException)
StartCoroutine(InitNewSession());
else
Debug.LogError(err.Message);
}
));| Exception | Status | When |
|---|---|---|
BadRequestException | 400 | Invalid UUID, missing fields |
AuthenticationException | 401 | Missing or invalid API key |
ForbiddenException | 403 | Not owner or persona unpublished |
NotFoundException | 404 | Resource not found |
RateLimitException | 429 | Rate limit exceeded |
ServerException | 500 | Internal server error |
💡Tip
The SDK automatically retries on 429 and 5xx errors with exponential backoff (up to 3 retries). Uses UnityWebRequest for full platform compatibility (WebGL, mobile, console).
Multi-Machine Example
// Discover available machines for a player
MachineInfo[] machines = await client.Machines.ListAsync(personaId, "player-001");
foreach (var m in machines)
{
string status = m.HasSession ? "active" : "available";
string linked = m.IsLinked ? " (linked)" : "";
Debug.Log($" {m.Name}: {status}{linked}");
}
// Start a specific machine
SessionInit session = await client.Chat.InitSessionAsync(
personaId: personaId,
userSessionId: "player-001",
playerName: "Alex",
playerGender: "non-binary",
machineId: machines[1].MachineId // target a specific scenario
);