Examples & recipes¶
The SDK ships working example scripts you can drop in, read, and adapt. They live in AISDK/Examples/Scripts/ and Examples/ in your project. Each one is small and focused on a single pattern.
Greeting & world events¶
| Script | What it shows |
|---|---|
GreeterTrigger |
Greet a player by username on enter and say goodbye on exit, from a trigger zone. Dual‑mode: on the NPC (NPC.Notify) or a separate object (NPC.NotifyTo). |
IdentityGreeter |
Greet generically ("Hello there") while tracking returning visitors by their stable account id — identity without speaking a name. |
WorldEventsNotifier |
Fire the common World Events at the NPC it's on (the companion to the Action Designer's Examples). |
SharedWorldEvents |
Fire world events from a shared object (a door, a zone) to one or more NPCs via NPC.NotifyTo. |
→ Background: World Events.
Players¶
| Script | What it shows |
|---|---|
PlayerRoster |
React to OnPlayerJoined / OnPlayerLeft and read the live roster with Networking.GetPlayers() — the base for player‑list UI, teams, spectator tools. |
→ Background: Player API.
Custom actions (the AI doing things)¶
| Script | What it shows |
|---|---|
RoomLightsBehaviour |
Custom control of room lights — color, RGB, power — across three actions (OnSetLightColor, OnSetLightRGB, OnLightPower), each reporting back with NPC.CommandResult / CommandError. |
StageDoorBehaviour |
A stateful custom action: open/close a sliding door (it remembers its state), using the Transform + AudioSource bindings — reading the scene, not just talking. |
LabAssistantBehaviour |
Drive an AI NPC's automation without a player for testing — moves cubes, toggles a light. |
AreaProbe |
Two ways for an NPC to know the live world: a context probe (WorldState(), ambient — always in the prompt) and an on‑demand query action (scan_area, "who's here?"). |
→ Background: Custom Actions.
Talking to a database¶
| Script | What it shows |
|---|---|
SupabaseTest |
Full CRUD against Supabase with HTTP.Get/Post/Patch/Put/Delete in coroutines — health check, create/read/update a profile. |
ScoreboardNpc |
End‑to‑end "what's my score?": Player.GetSpeakerUserId() keys a Supabase lookup, and an async action returns the number inline so the NPC speaks it in one turn. |
→ Background: HTTP & Supabase.
Engine & Unity recipes¶
Copy‑paste companions for the Engine & Unity API guides — self‑contained, no scene wiring required.
Look-to-interact (physics + camera + input)¶
Raycast from the player's view; highlight whatever they're looking at and let them press E to use it. Pairs with Physics and Input, time & camera.
Put this on any always‑on object (an empty "GameController"):
using UnityEngine;
using NexusVM.Unity;
class LookToInteract : NexusBehaviour
{
public float reach = 4f; // how far the player can reach
GameObject hovered;
protected override void Update()
{
Camera cam = Camera.main;
if (cam == null) return;
// What is the player looking at, within reach?
GameObject target = null;
RaycastHit hit;
if (Physics.Raycast(cam.transform.position, cam.transform.forward, out hit, reach)
&& hit.collider.CompareTag("Interactable"))
target = hit.collider.gameObject;
// Hover changed → tell the old and new objects
if (target != hovered)
{
if (hovered != null) hovered.SendMessage("OnHoverExit");
if (target != null) target.SendMessage("OnHoverEnter");
hovered = target;
}
if (hovered != null && Input.GetKeyDown("e"))
hovered.SendMessage("OnUse");
}
}
Put this on each interactable object (tag it Interactable, give it a Collider + Renderer):
using UnityEngine;
using NexusVM.Unity;
class Interactable : NexusBehaviour
{
Renderer rend;
Color baseColor;
protected override void Start()
{
rend = GetComponent<Renderer>();
baseColor = rend.GetColor();
}
public void OnHoverEnter() { rend.SetColor(Color.yellow); } // highlight
public void OnHoverExit() { rend.SetColor(baseColor); } // restore
public void OnUse() { Debug.Log(gameObject.name + " used!"); }
}
Teaches: Physics.Raycast + Camera.main, Collider.CompareTag, SendMessage between scripts, Input.GetKeyDown, and Renderer.SetColor/GetColor.
Score HUD (build UI from script)¶
A self‑contained heads‑up display that creates its own canvas, shows a score, and adds a +1 button — no scene UI to set up. Pairs with UI.
using UnityEngine;
using NexusVM.Unity;
class ScoreHud : NexusBehaviour
{
int score;
Text label;
protected override void Start()
{
UI.EnsureEventSystem(); // so the button receives clicks
GameObject canvas = UI.CreateCanvas();
// CreateLabel(parent, name, text, fontSize, posX, posY, sizeX, sizeY)
label = UI.CreateLabel(canvas, "Score", "Score: 0", 32, 0, 420, 400, 60);
// CreateButton(parent, name, label, posX, posY, sizeX, sizeY)
Button add = UI.CreateButton(canvas, "Add", "+1", 0, -360, 160, 56);
Button.AddClickListener(add, "OnAdd"); // calls OnAdd() below
}
public void OnAdd()
{
score++;
Text.SetText(label, "Score: " + score);
}
}
Teaches: UI.CreateCanvas/CreateLabel/CreateButton, click wiring with Button.AddClickListener(button, "Method"), and updating a label with Text.SetText. Swap the local score for a Storage or HTTP read to show shared state.
Common recipes¶
Resolve a player from a trigger:
void OnTriggerEnter(Collider other)
{
string id = Player.IdOf(other.gameObject); // "" if not a player
if (id == "") return;
// ... do something with id
}
Notify one or many NPCs from a shared object:
public GameObject[] targetNpcs; // drag NPC(s) in the inspector
void Fire(string eventId, string json)
{
if (targetNpcs == null || targetNpcs.Length == 0) NPC.Notify(eventId, json);
else for (int i = 0; i < targetNpcs.Length; i++)
if (targetNpcs[i] != null) NPC.NotifyTo(targetNpcs[i], eventId, json);
}
Track a player across sessions (durably): key your DB rows by Player.GetUserId and write with HTTP; use Storage as a same‑session cache.