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

# Set up a VR scenario from scratch

> Create a complete VR training scenario with activities, steps, and session flow.

**Applies to:** Molca VR SDK

## Overview

This recipe shows you how to create a complete VR training scenario from scratch. You'll create a Scenario Data Config asset, set up a scenario scene with ScenarioManager, add activities with VR-specific steps, and configure the session flow. This is the foundation for building immersive VR training experiences with ordered tasks, scoring, and backend integration.

## Prerequisites

* **SDK modules**: Molca Core, Molca VR SDK installed
* **Unity setup**: RuntimeManager configured, XR Plugin Management installed, GlobalSettings configured
* **Prior knowledge**: [RuntimeManager](/core/runtime-manager), [SequenceController](/core/sequence-controller), [Step](/core/step)

## Step-by-step

### Step 1: Create a Scenario Data Config asset

Create a `ScenarioDataConfig` asset to register your scenario collections and configure execution mode.

```csharp theme={null}
// In the Unity Editor:
// 1. Right-click in Project → Create → Molca → VR → Scenario Data Config
// 2. Name it "MyScenarioDataConfig"
// 3. Add it to your GlobalSettings asset's SettingModules list
```

**Why this works**: The `ScenarioDataConfig` is a `SettingModule` that tells the runtime which scenarios exist and how to resolve them by ID. It's loaded during `RuntimeManager` initialization and used by the session system to find scenario assets.

### Step 2: Create a Simulation Scenario Data asset

Create a `SimulationScenarioData` asset that defines your training scenario metadata.

```csharp theme={null}
// In the Unity Editor:
// 1. Right-click in Project → Create → Molca → VR → Simulation Scenario Data
// 2. Name it "FireSafetyTraining"
// 3. Set the following fields:
//    - Scenario Name: "Fire Safety Training"
//    - Ref Id: (auto-generated, e.g., "fire-safety-001")
//    - Time Limit: 300 (5 minutes, or 0 for no limit)
//    - Single Player Plan:
//      - Scenario Scene → Scene Name: "FireSafetyScene" (or use Scene Reference for Addressables)
//      - Preload Scenes: (leave empty for simple scenarios; add environment scenes if needed)
```

**Why this works**: `SimulationScenarioData` holds the metadata that links your scenario asset to its Unity scenes via the **`SceneLoadPlan`** structure. The `RefId` is used for local lookups, while `ScenarioId` (org ID, set later) links to backend scenarios. The `SceneLoadPlan` supports ordered multi-scene loading — preload scenes load first (environment, shared assets), then the main scenario scene.

### Step 3: Add the scenario to ScenarioDataConfig

Add your scenario data asset to the `ScenarioDataConfig` collections.

```csharp theme={null}
// In the Unity Editor:
// 1. Select your "MyScenarioDataConfig" asset
// 2. In the Inspector, expand "Scenario Collections"
// 3. Add a new collection entry
// 4. Drag your "FireSafetyTraining" asset into the collection
```

**Why this works**: The `ScenarioDataConfig` uses collections to register available scenarios. At runtime, methods like `GetScenarioDataByScenarioId` search these collections to resolve scenario references.

### Step 4: Create the scenario Unity scene

Create a new Unity scene for your VR scenario and add the VR Scenario prefab.

```csharp theme={null}
// In the Unity Editor:
// 1. File → New Scene
// 2. Save as "FireSafetyScene" (matching the Scene Name in your scenario data)
// 3. Drag the "[VR Scenario]" prefab into the scene
//    (typical path: Assets/_MolcaSDK/_VR/Prefabs/Base/)
// 4. This prefab includes: XR rig, ScenarioManager, scenario UI, and VR player setup
```

**Why this works**: The `[VR Scenario]` prefab provides the complete VR runtime infrastructure: XR Origin for tracking, `ScenarioManager` for orchestration, scenario UI for pause/completion, and player management. This ensures consistent VR setup across all scenarios.

### Step 5: Configure ScenarioManager

Select the `ScenarioManager` component in your scene and configure it to reference your scenario data.

```csharp theme={null}
// In the Unity Editor:
// 1. Select the GameObject with ScenarioManager (usually on the [VR Scenario] prefab root)
// 2. In the Inspector, set:
//    - Scenario Data: Drag your "FireSafetyTraining" asset here
//    - Auto Start: Check this for testing (uncheck for session-based flow)
//    - Use Session Manager: Uncheck for testing, check for production
//    - Start All Activities Simultaneously: Usually unchecked (sequential activities)
```

**Why this works**: `ScenarioManager` is the runtime orchestration component that manages scenario state (`Inactive`, `Active`, `Completed`), drives activities in order, and integrates with the session system. The `scenarioData` reference links the scene to your scenario metadata.

### Step 6: Create activity GameObjects

Under the `ScenarioManager`, create child GameObjects for each training activity.

```csharp theme={null}
// In the Unity Editor:
// 1. Right-click ScenarioManager → Create Empty
// 2. Rename to "Activity1_ExtinguisherGrab"
// 3. Add Component → Molca → VR → Scenario Activity
// 4. Add Component → Molca → Sequence → Sequence Controller
// 5. Set Activity ID: "extinguisher-grab" (must match ActivityData.RefId if using session)
// 6. Repeat for additional activities (e.g., "Activity2_FireExtinguish")
```

**Why this works**: Each `ScenarioActivity` wraps a `SequenceController` and integrates with scoring and session posting. The `activityId` field links the runtime component to backend activity metadata when using connected sessions.

### Step 7: Add VR steps to activities

Create child GameObjects under each activity and add VR step components.

```csharp theme={null}
// In the Unity Editor:
// For Activity1_ExtinguisherGrab:
// 1. Right-click Activity1_ExtinguisherGrab → Create Empty
// 2. Rename to "Step1_LookAtExtinguisher"
// 3. Add Component → Molca → VR → Steps → Look At Step
// 4. Configure the Look At Step:
//    - Target: Drag the fire extinguisher GameObject
//    - Duration: 2.0 seconds
//
// 5. Create another child: "Step2_GrabExtinguisher"
// 6. Add Component → Molca → VR → Steps → Grab Step
// 7. Configure the Grab Step:
//    - Target Object: Drag the fire extinguisher GameObject
//    - Require Correct Hand: Optional (check if specific hand required)
```

**Why this works**: VR steps are specialized `Step` subclasses that handle VR interactions. `LookAtStep` completes when the user gazes at a target for a duration. `GrabStep` completes when the user grabs a specific object. The `SequenceController` executes these steps in hierarchy order.

### Step 8: Wire activities to ScenarioManager

Add your activity GameObjects to the `ScenarioManager.activities` array.

```csharp theme={null}
// In the Unity Editor:
// 1. Select the ScenarioManager GameObject
// 2. In the Inspector, expand "Activities"
// 3. Set Size to match your activity count (e.g., 2)
// 4. Drag Activity1_ExtinguisherGrab into Element 0
// 5. Drag Activity2_FireExtinguish into Element 1
```

**Why this works**: The `ScenarioManager` executes activities in array order (unless `startAllActivitiesSimultaneously` is checked). When an activity's sequence completes, the manager advances to the next activity or completes the scenario.

### Step 9: Configure session flow (optional)

For production scenarios with backend integration, configure the session flow.

```csharp theme={null}
using Molca;
using MolcaSDK.VR.Scenario.Session;
using UnityEngine;

public class ScenarioBootstrap : MonoBehaviour
{
    private ScenarioSessionManager _session;

    private async void Start()
    {
        await RuntimeManager.WaitForInitialization();
        _session = RuntimeManager.GetSubsystem<ScenarioSessionManager>();
        
        if (_session == null)
        {
            Debug.LogError("ScenarioSessionManager not found");
            return;
        }

        // Subscribe to events
        _session.OnError.AddListener(OnSessionError);
        _session.OnLoadingProgress.AddListener(OnLoadingProgress);

        // Create session (orgScenarioId from backend)
        bool created = await _session.CreateSessionAsync(orgScenarioId: 42, mode: "TRAINING");
        if (!created)
        {
            Debug.LogError("Failed to create session");
            return;
        }

        // Load scenario scene
        await _session.LoadSessionWithProgressAsync();
    }

    private void OnDestroy()
    {
        if (_session != null)
        {
            _session.OnError.RemoveListener(OnSessionError);
            _session.OnLoadingProgress.RemoveListener(OnLoadingProgress);
        }
    }

    private void OnSessionError(string message) => Debug.LogError($"Session error: {message}");
    private void OnLoadingProgress(float progress, string status) => Debug.Log($"Loading: {progress:P0} - {status}");
}
```

**Why this works**: `ScenarioSessionManager` handles backend session creation, scene loading via Addressables, and progress tracking. The `CreateSessionAsync` call establishes a session with the backend, and `LoadSessionWithProgressAsync` loads the scenario scene and starts the training. This flow requires `useSessionManager` to be checked on `ScenarioManager`.

## Complete example

Here's a complete custom VR step that waits for the user to press a button before completing:

```csharp theme={null}
using Molca.Sequence;
using UnityEngine;
using UnityEngine.XR.Interaction.Toolkit;

/// <summary>
/// A VR step that completes when the user presses a specific button.
/// </summary>
public class ButtonPressStep : Step
{
    [SerializeField] private XRSimpleInteractable button;
    [SerializeField] private string instructionText = "Press the red button";

    protected override void OnStepActivated()
    {
        base.OnStepActivated();
        Debug.Log(instructionText);
        
        if (button != null)
        {
            button.selectEntered.AddListener(OnButtonPressed);
        }
    }

    private void OnButtonPressed(SelectEnterEventArgs args)
    {
        Debug.Log("Button pressed, step complete");
        Complete();
    }

    protected override void OnStepDeactivated()
    {
        base.OnStepDeactivated();
        
        if (button != null)
        {
            button.selectEntered.RemoveListener(OnButtonPressed);
        }
    }
}
```

Attach this script to a child GameObject under your `ScenarioActivity`, and it will wait for the user to interact with the specified button before advancing.

## Troubleshooting

* **Scenario never starts**: Ensure `RuntimeManager.WaitForInitialization()` completes before calling `StartScenario()`. If using `autoStart`, verify the `ScenarioManager` is active in the scene.
* **Activities don't advance**: Check that each activity's `SequenceController` is properly configured and that steps call `Complete()` when finished. Use the [Sequence Visualizer](/core/sequence-visualizer) to debug step hierarchy.
* **Session creation fails**: Verify `ScenarioNetworkConfig` endpoints are correct, authentication token is valid, and `orgScenarioId` exists in the backend. Check `OnError` event logs.
* **Scene doesn't load**: Confirm the `SceneLoadPlan` is configured in `SimulationScenarioData` — check that `singlePlayerPlan.scenarioScene` has either `sceneName` or `sceneReference` set. For Addressables, verify the scene is marked as Addressable and the key matches exactly.
* **Steps execute out of order**: Steps execute in hierarchy order (top to bottom). Reorder GameObjects in the Hierarchy or check for parallel step configurations.
* **Preload scenes don't load**: Verify `singlePlayerPlan.preloadScenes` array is populated. Index 0 loads as Single (active scene); subsequent entries load Additive. Check console for scene load errors.
* **Scene loads but objects missing**: Check `waitForRefIds` on preload scene entries — the executor waits up to 15 seconds for those RefIds to be registered in `ReferenceManager`. If timeout occurs, check console warnings.

## Related

* [Scenario Data](/vr/scenario-data) — ScriptableObject asset that defines scenario metadata and scene loading
* [Scenario Data Config](/setup/scenario-data-config) — scenario collections and execution mode configuration
* [VR session flow](/setup/vr-session-flow-how-to) — session creation, loading, and event handling
* [ScenarioManager](/vr/scenario-manager) — scenario state machine and activity orchestration
* [Recipe: Set up a basic sequence](/recipes/setup-basic-sequence) — foundational sequence and step concepts
* [VR content hierarchy](/vr/sdk-content-hierarchy) — understanding the module → scenario → activity → step structure
* [Look At Step](/vr/steps/look-at-step) — VR step for gaze-based interactions
* [Grab Step](/vr/steps/grab-step) — VR step for object grabbing interactions
