> For the complete documentation index, see [llms.txt](https://docs.convai.com/api-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.convai.com/api-docs/plugins-and-integrations/convai-unity-sdk/features/scene-metadata/usage-examples.md).

# Scene metadata usage examples

The examples below cover realistic setups for training simulations and interactive experiences. Each is self-contained: Inspector configuration is described first, followed by any scripting needed to complete the behavior. Start with whichever matches your current complexity level.

### Example 1: Medical training simulation — anatomy lab

**Scenario:** A surgical training simulation where a medical instructor NPC guides trainees through an anatomy lab. The character must recognize and describe physical models and equipment in the room — trainees ask questions like "What is this organ?" or "Where is the aorta?"

#### Setup

Add `ConvaiObjectMetadata` to each anatomy model and equipment item:

| Object Name      | Object Description                                                                                           |
| ---------------- | ------------------------------------------------------------------------------------------------------------ |
| Heart Model      | Life-size anatomical heart model on the center examination table. Shows all four chambers and major vessels. |
| Liver Model      | Adult liver model mounted on the left side of the display rack. Hepatic veins are color-coded.               |
| Surgical Scalpel | Standard surgical scalpel resting on the instrument tray. Handle is blue.                                    |
| Stethoscope      | Stethoscope hanging on the hook next to the examination table.                                               |

Add `ConvaiSceneMetadataCollector` to the `ConvaiManager` GameObject. Enable **Collect On Start**.

No scripting required. The instructor character receives all descriptions at session start and can answer anatomy questions grounded in the actual scene.

{% hint style="success" %}
The trainee asks: "What models are available for study?" The instructor responds: "On the center table you have a life-size heart model showing all four chambers, and to your left on the display rack is an adult liver model with color-coded hepatic veins."
{% endhint %}

### Example 2: Industrial safety drill — phase-based metadata

**Scenario:** A safety training module with multiple drill phases. Each phase introduces different hazards and equipment. The AI instructor should only know about the props relevant to the current phase.

#### Setup

Leave **Collect On Start** disabled on `ConvaiSceneMetadataCollector`. Use a script to send metadata after each phase loads.

```csharp
using Convai.Runtime.SceneMetadata;
using UnityEngine;

public class SafetyDrillController : MonoBehaviour
{
    [SerializeField] private ConvaiSceneMetadataCollector _metadataCollector;
    [SerializeField] private ConvaiObjectMetadata[] _phase1Props;
    [SerializeField] private ConvaiObjectMetadata[] _phase2Props;

    private ConvaiObjectMetadata[] _allProps;

    void Awake()
    {
        _allProps = GetComponentsInChildren<ConvaiObjectMetadata>(includeInactive: true);
    }

    public void LoadPhase(int phase)
    {
        // Exclude all props
        foreach (var prop in _allProps)
            prop.IncludeInMetadata = false;

        // Enable only the current phase's props
        ConvaiObjectMetadata[] activeProps = phase == 1 ? _phase1Props : _phase2Props;
        foreach (var prop in activeProps)
            prop.IncludeInMetadata = true;

        // Send the updated payload
        if (_metadataCollector.IsReadyToSendMetadata())
            _metadataCollector.CollectAndSendSceneMetadata();
    }
}
```

Each phase sends only its relevant props to Convai. The instructor adapts its knowledge to the current drill context without knowing about props from other phases.

### Example 3: Interactive museum — exhibit guide

**Scenario:** A virtual museum guide character answers visitor questions about exhibits across multiple rooms. The guide should know what each exhibit is, where it is, and what is significant about it.

#### Setup

Add `ConvaiObjectMetadata` to each exhibit's root GameObject. Write descriptions that include location cues and key facts:

| Object Name              | Object Description                                                                                                                      |
| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------- |
| Rosetta Stone Replica    | Large stone slab in the Egyptian gallery, center of Room 2. Contains the same text in hieroglyphics, Demotic script, and Ancient Greek. |
| Roman Legionnaire Armor  | Full legionnaire battle armor on a mannequin in Room 3, left wall. Dated to 1st century AD.                                             |
| Viking Longship Fragment | Preserved bow section of a 9th-century Viking longship, suspended from the ceiling in the Norse gallery.                                |

Enable **Collect On Start**. When a visitor asks "What is in Room 2?", the guide responds with accurate, description-grounded information.

Write descriptions from the perspective of what a knowledgeable guide would say. Include room location, visual identifiers, and relevant context. The AI uses the `Object Description` field verbatim as grounding for its responses.

### Example 4: Runtime context update — combining Scene Metadata and Dynamic Context

**Scenario:** A warehouse training scenario where items can be moved or removed. When a hazard is cleared, the AI should stop referencing it. When a new tool arrives, the AI should immediately know about it.

#### Excluding a cleared object

```csharp
public void OnHazardCleared(ConvaiObjectMetadata hazardMetadata)
{
    // Remove from AI context without destroying the GameObject
    hazardMetadata.IncludeInMetadata = false;

    if (_collector.IsReadyToSendMetadata())
        _collector.CollectAndSendSceneMetadata();
}
```

#### Adding a new object at runtime

```csharp
public void OnToolDelivered(GameObject toolObject, string toolName, string toolDescription)
{
    // Add metadata component at runtime
    var metadata = toolObject.AddComponent<ConvaiObjectMetadata>();
    metadata.ObjectName = toolName;
    metadata.ObjectDescription = toolDescription;
    // Component auto-registers on OnEnable

    if (_collector.IsReadyToSendMetadata())
        _collector.CollectAndSendSceneMetadata();
}
```

{% hint style="info" %}
Scene Metadata and Dynamic Context are complementary. Use Scene Metadata to tell the AI what exists in the scene. Use Dynamic Context to tell the AI what is happening at runtime. Pairing `CollectAndSendSceneMetadata()` with `SetState` calls on `IConvaiDynamicContext` gives the character both object awareness and event awareness simultaneously.
{% endhint %}

### Example 5: Warehouse loading bay — door status as a tracked property

**Scenario:** A warehouse safety trainer NPC must always know whether the loading bay door is open or closed, and must react immediately if the door's sensor reports a jam. Re-sending an `Object Description` after every door movement would need a script that intercepts each state change and re-runs scene metadata collection. A tracked property keeps the character current without that extra step.

#### Setup (declarative — reflection-based polling)

Add `ConvaiObjectMetadata` to the loading bay door's GameObject. Set **Object Name** to `LoadingBayDoor` and **Object Description** to a fixed description of the door's location and purpose. In **Tracked Properties**, add one `ConvaiTrackedContextProperty` entry:

| Field              | Value                                                             |
| ------------------ | ----------------------------------------------------------------- |
| Property Name      | `DoorStatus`                                                      |
| Source Component   | The door's controller script                                      |
| Source Member Name | `Status` — the public property that reports the current state     |
| Initial Value      | `Closed` — used only if the reflection read fails                 |
| Reaction           | `Auto` — let Convai decide whether the change is worth mentioning |

```csharp
using UnityEngine;

public class LoadingBayDoorController : MonoBehaviour
{
    [SerializeField] private bool _isOpen;

    public string Status => _isOpen ? "Open" : "Closed";

    public void SetOpen(bool isOpen) => _isOpen = isOpen;
}
```

`ConvaiObjectMetadata` polls every tracked property that has a **Source Component** on a shared 0.25-second timer. When `LoadingBayDoorController.Status` changes, the updated value broadcasts to every connected character under the state key `LoadingBayDoor.DoorStatus` — no manual re-send required.

#### Setup (imperative — pushed from a code event)

A sensor jam is a discrete event, not a value read every frame, so push it directly instead of wiring a reflection source. Add a second **Tracked Properties** entry with **Property Name** set to `SensorFault`, **Initial Value** set to `None`, and **Source Component** left empty. Call `SetTrackedPropertyValue` from the sensor's own event handlers:

```csharp
using Convai.Runtime;
using Convai.Runtime.SceneMetadata;
using UnityEngine;

public class DoorSensorMonitor : MonoBehaviour
{
    [SerializeField] private ConvaiObjectMetadata _doorMetadata;

    public void OnSensorJamDetected()
    {
        _doorMetadata.SetTrackedPropertyValue("SensorFault", "Jammed", ConvaiRespondMode.MustRespond);
    }

    public void OnSensorCleared()
    {
        _doorMetadata.SetTrackedPropertyValue("SensorFault", "None", ConvaiRespondMode.Silent);
    }
}
```

`SetTrackedPropertyValue` builds the state key `LoadingBayDoor.SensorFault` and fans the new value out to every connected character immediately, bypassing the poll timer entirely.

#### Expected outcome

When a trainee asks "Is the loading bay door open?", the trainer answers from the current `LoadingBayDoor.DoorStatus` value instead of a description written at session start. If `OnSensorJamDetected()` fires while the door is moving, the `MustRespond` reaction on `SensorFault` makes the trainer speak up immediately:

> "Stop — the loading bay door sensor reported a jam. Do not proceed until maintenance clears it."

If the component is disabled and re-enabled, `DoorStatus` re-reads `LoadingBayDoorController.Status` through its **Source Component** again, while `SensorFault` — which has no runtime source — resets to its **Initial Value** of `None`. Disabling or destroying `ConvaiObjectMetadata` removes both state keys from every character that was tracking them.

### Next steps

{% content-ref url="/pages/66fddc4b0f911e97d589403a45f3ae569eb83b5d" %}
[Troubleshoot scene metadata](/api-docs/plugins-and-integrations/convai-unity-sdk/features/scene-metadata/troubleshooting-and-diagnostics.md)
{% endcontent-ref %}

{% content-ref url="/pages/HLRHVibG6Nqvot1DGfvc" %}
[Dynamic context](/api-docs/plugins-and-integrations/convai-unity-sdk/features/dynamic-context.md)
{% endcontent-ref %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.convai.com/api-docs/plugins-and-integrations/convai-unity-sdk/features/scene-metadata/usage-examples.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
