# Zoe for Unity - Help Center

Learn how to install and use Zoe for Unity, and get answers to your questions.

Welcome to the **Zoe for Unity** Help Center. Find here all information to get started with this plugin for the Unity game engine.\
\
**Current version:** 4.0 – [Download Zoe for Unity](https://zoeimmersive.com/unity/download/) \*\
**Release date:** 2026-02-11\
**Compatible with:** Unity 6.3 LTS (6000.3.5f2) – [Download](unityhub://6000.3.5f2/3fa8bc678cb0)

\* You need a license to download Zoe for Unity. You can buy one [here](https://zoeimmersive.com/contact/).

{% hint style="warning" %}
This Help Center is for the **Zoe for Unity plugin**, not the **Zoe app**. The app has a separate Help Center which can be accessed [here](https://docs.zoeimmersive.com/).
{% endhint %}

### Release Notes

#### New Features

* Updated to Unity 6 and URP
* Added Build Target Window in the Zoe menu to switch from Meta build settings to WebGL (with validation for minimal Android version)
* New condition added: 'Button Clicked' for UI Button support

#### Improvements / Fixes

* Internal improvements (improved registration of custom actions/conditions using ActionRegistry/ConditionRegistry Attribute)
* Improved Desktop Controller with 2D cursor
* All actions have proper 'Back & Forth' behavior

#### Known Issues

* Collision condition has issues when sometimes used with dependencies:
  1. When having two interactions dependent on each other that are detecting the collision between the same objects, the second one might not trigger.
  2. Collision condition when having an interaction that is repeating, with two dependencies (not all required) and one of them is repeating as well is not triggering on the validation of the repeated interaction, this might cause some loops of interactions to only work once and not when the second loop is supposed to start.


# Setting up Unity

What you need before installing Zoe

Zoe for Unity is a plugin for the game engine [Unity](https://unity.com/).&#x20;

{% embed url="<https://youtu.be/UqG0sm9w83w>" %}

* Follow the instructions and install the recommended Unity compatible version stated on our [download page.](https://unity.zoeimmersive.com/installation/www.zoeimmersive.com/unity/download) Do not use the version in the tutorial, just take the most up to date version you see [here](/).
* Make sure to install the necessary packages (iOS, Android,...) depending on the platform you want to build for.
* When the Unity version has been installed, click on 'New Project'.
* Choose the `3D Core` template, fill the Project Settings and click on `Create Project`.

<figure><img src="/files/uB8wYXP2GMs4CfeMTF84" alt=""><figcaption><p>New Project</p></figcaption></figure>

* Wait until Unity opens up the project.


# Installing Zoe for Unity

Zoe for Unity is a **plugin** that requires the Unity game engine. To install it, follow the instructions below.

{% embed url="<https://youtu.be/0-cAePuYc74>" %}

### Installing Unity

{% hint style="info" %}
Instructions updated for Unity 6.
{% endhint %}

* Start by installing Unity Hub for your operating system [here](https://unity.com/download).&#x20;
* From the plugin's [download page](https://zoeimmersive.com/unity/download), install the recommended Unity compatible version listed in the "Core Plugin" section simply by clicking on it.

{% hint style="info" %}
Note: You need an account to access the Zoe for Unity download page. If you don't have one yet, you can purchase one [here](https://zoeimmersive.com/pricing/).
{% endhint %}

{% hint style="warning" %}
Always download the recommended Unity version listed [here](https://zoeimmersive.com/unity/download).
{% endhint %}

* Install the necessary packages depending on the platform you want to build for. Zoe for Unity is compatible with Web, Android (for VR headsets), macOS and Windows. If unsure, you can always add new packages later.
* When the Unity version has been installed, click on 'New Project'.
* Choose the `Universal 3D` core template (named "3D" in versions prior to Unity 6), name your project and choose a folder location, then click on `Create project`.

<figure><img src="/files/68ZrGyHBZlBVbLk0V2dh" alt=""><figcaption><p>Create a new project with the "Universal 3D" core template.</p></figcaption></figure>

{% hint style="info" %}
Note: Prior to Unity 6, the "Universal 3D" core template was just named "3D".
{% endhint %}

* Wait until Unity opens up the project.

### Installing Zoe for Unity

* Download the Zoe for Unity **core plugin** [here](https://zoeimmersive.com/unity/download/) (you need to be logged in). If you don't have an account yet, you can purchase one [here](https://zoeimmersive.com/pricing/).
* If it's not already opened, open the **Unity project** you previously created.

{% hint style="info" %}
Make sure you are logged into your **Unity account**. For this, check the upper-left corner of the Editor (upper-right corner prior to Unity 6). Make sure you can see your **username** and that nothing is grayed out.
{% endhint %}

* Once downloaded, double-click on the Zoe for Unity **.unitypackage** file.
* Unity should automatically prompt the following popup. Click on `Import`.

<figure><img src="/files/JaAuu1WJtY2NBGnfhBSm" alt="" width="300"><figcaption><p>Import Window</p></figcaption></figure>

* An initialization process will start and you will get the following window. Press on `Install Zoe`:

<figure><img src="/files/Tuc9JOMVOzn8EwAiyjuP" alt="" width="525"><figcaption><p>Install Window</p></figcaption></figure>

{% hint style="info" %}
If for some reason you don't see this window pop, try one of the following:

* If you see a **Zoe** item in the top bar menu, click on it and select 'Open Initialization Tool' (or 'Reset SDK Initialization' in older versions).
* Or quit and re-open Unity, then try importing the plugin again.
  {% endhint %}

The installation process takes a few minutes.

{% hint style="warning" %}
The installation process may pause if Unity in not kept as an active window on your computer. If it does, simply make the Unity window active again to resume installation.
{% endhint %}

During the installation you will get the following popup windows to acknowledge:

<div><figure><img src="/files/kjulWuqlmYmddMq1hIZT" alt="" width="259"><figcaption><p>'Scoped registries' popup</p></figcaption></figure> <figure><img src="/files/Hh3rp5iXRYRqqCz9nMGD" alt="" width="259"><figcaption><p>'New layers' popup</p></figcaption></figure> <figure><img src="/files/9MXCCBRLkl4zkB5gg1V1" alt="" width="259"><figcaption><p>'New tags' popup</p></figcaption></figure></div>

When the process is finished, the following popup will ask to restart the Unity editor. Click OK.

<figure><img src="/files/pGZPkVd8olMzWjoEKBFx" alt="" width="259"><figcaption><p>'Editor Restart' popup window</p></figcaption></figure>

When your project reopens, it will have the following folder structure. You'll also get a new `Zoe` section in the top bar menu.

<figure><img src="/files/7kXLyix2YkysbsCDfhqH" alt="" width="233"><figcaption><p>Folder structure after installation</p></figcaption></figure>

### Updating Zoe for Unity

Follow these steps to update the Zoe for Unity plugin:

* Delete the 'Zoe' folder in your project.&#x20;
* Import the most up-to-date version of the plugin [here](https://zoeimmersive.com/unity/download/).&#x20;
* From the Zoe top bar menu, click on 'Open Initialization Tool' (or 'Reset SDK Initialization' in older versions) then follow the usual install process.


# Project Settings

{% hint style="info" %}
From Unity 6, Zoe for Unity switched from using the Meta (Oculus) SDK to OpenXR. OpenXR works with all major VR devices working with Android.
{% endhint %}

By default, Zoe will automatically be configured to work with XR. If you're planning to export your project for web or desktop however, you'll need to change some settings.

<div><figure><img src="/files/vGHUBUM5e2gDbYHjjBCa" alt=""><figcaption><p>Settings since Unity 6</p></figcaption></figure> <figure><img src="https://connect-prd-cdn.unity.com/20200831/learn/images/e7751d15-97d6-4acd-a15a-d8b6cffe84ef_XRplugin_oculus.PNG.2000x0x1.webp" alt=""><figcaption><p>Settings prior to Unity 6</p></figcaption></figure></div>

### Web Settings

To change your project for the Web, do the following:

* &#x20;Go to Edit > Project Settings;
* From the left sidebar, select `XR Plug-in Management;`

{% hint style="info" %}
Note: If you don't see XR Plug-in Management in the sidebar it means Zoe was not properly installed. In that case, you should go through the installation process again.
{% endhint %}

* Select the Web tab, recognizable by its world globe icon;

{% hint style="info" %}
If the Web tab is not available, you need to install Web packages first. To do that, go to and click on `Install`.
{% endhint %}

* Uncheck `Initialize XR on Startup`.

### XR Settings

If you've changed settings and need to set up your project for XR again, or just want to check if your settings are correct, follow this procedure:

* &#x20;Go to Edit > Project Settings;
* From the left sidebar, select `XR Plug-in Management;`

{% hint style="info" %}
Note: If you don't see XR Plug-in Management in the sidebar it means Zoe was not properly installed. In that case, you should go through the installation process again.
{% endhint %}

* Select the Android tab, recognizable by its Android icon;
* Check `Initialize XR on Startup`.


# Basic Scene

Head to `Zoe > SDK > _BasicScene` and open the **BasicScene** scene. Here you can see the basic setup you need in a scene for Zoe to work:

<figure><img src="/files/amlIl209pmK36Zwdw3Wj" alt=""><figcaption><p>Basic Scene Setup</p></figcaption></figure>

After following the previous steps simply press 'Play' in the top center of the Unity Editor and test the scene.

If everything is working correctly you should see your two controllers and a green apple that you are able to grab (using the triggers of your controllers).

You are now ready to start working with Zoe!

*If the camera does not move, or the controllers don’t work, check again all of the previous steps. In particular, make sure the XR Plugin is properly set (‘Initialize on Startup’ should be checked).*


# Interaction Rig

Zoe uses its own camera with the following functionalities:

* **Head and Controllers Tracking**: system for tracking the head and hand controllers.
* **Navigation**: Allows you to move in the virtual world.
* **Manipulation:** Input for manipulating objects with settings for visual feedbacks from the controllers.


# Create an Interaction Rig

In order for the plugin to work properly you need to convert the standard camera into Zoe's **Interaction Rig**. There are two ways of doing this:

a) In the camera's Inspector, click on the `Convert into Interaction Rig (IO)` button;

b) Or right-click the standard Unity camera in a scene and select **Zoe > Convert into Interactive Rig.**

{% embed url="<https://youtu.be/dbVUlkUf-Lg>" %}

<div><figure><img src="/files/M80JMZpupl0NEPeAHKTH" alt=""><figcaption><p>a) Button in a standard camera's Inspector</p></figcaption></figure> <figure><img src="/files/neq7fXHsRExxjAT6vsgV" alt=""><figcaption><p>b) From a camera's contextual menu</p></figcaption></figure></div>

{% hint style="info" %}
Note that when the camera is converted, two new elements can be seen in the scene:

**InteractionRig (IO):** this is the element representing the user in the experience. You can change its position, customize controllers and raycast as well as set the navigation mode (more details [here](/getting-started/navigation-modes)).

**S\_RenderingCamera:** this is the actual camera rendering, you should only modify it if you want to change the Flags Clear or add post-processing effects. **Do not change its position as it will automatically follow the rig at runtime.**
{% endhint %}

<figure><img src="/files/odPRVwWJlazQZKKOqUne" alt="" width="264"><figcaption><p>Do not modify the S_renderingCamera.</p></figcaption></figure>


# Structure & Settings

Once converted, your new camera will have the following structure in the Hierarchy window:

<figure><img src="/files/wblyL1OPk8Vo59VFNIoo" alt="" width="333"><figcaption><p>Interaction Rig Structure</p></figcaption></figure>

* **Head (IO):** it contains the Camera you just converted. It is the object that is used to track the user head movements. The Head (IO) game object has more or less the standard Interactive Object structure of Zoe (details in IO section) with the addition of the Player Torso object. The Torso represents the approximate position of the torso below the head. You can change the distance between the head and the torso in the inspector.
* **Right Hand (IO):** Represents the right hand of the player/user.
* **Left hand (IO):** Represents the left hand of the player/user.

The Interaction Rig represents the user in the experience, when selecting it, inside the Inspector window you find the options that can be set and customized for the user: [**Navigation**](/getting-started/navigation-modes) & **Manipulation**.

<figure><img src="/files/W0yRYN1rcTNhWyV8I1zh" alt=""><figcaption><p>Manipulation and raycast settings</p></figcaption></figure>

* **Default Input:** choose an input that will be used by default for manipulating objects in the scene.
* **Controllers Raycast:** lasers or raycasts come out of the controllers by default to help the user in the manipulation of objects.
* **Default Laser Parameters:** settings for the laser by default, shown from the beginning (laser can be hidden or customised)
* **Manipulation Laser Parameters**: settings for the laser when it hits and Interactive Object inside the scene (laser can be customised depending on the distance the controller is from the Interactive Object).


# Testing without a headset

Use your mouse and keyboard to playtest your experience.

{% embed url="<https://youtu.be/-LQNgk22jrc>" %}

To test your experience without a headset, you can use **Desktop Camera Control** which can be found at the root of your Interaction Rig. Once the script is added, you will be able to look around you with your mouse, move around using your keyboard's `W`, `A`, `S`, and `D` keys and pick up objects with the `E` key.&#x20;

<figure><img src="/files/svJgiUYTQhOEVwEg0JcU" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
Since your movements are more restricted than in VR, you can use the **Levitate** method to pick up your objects easily in this mode.&#x20;
{% endhint %}

{% hint style="info" %}
If using the **Grab** method, make sure the grab distance of your objects is long enough so that you can grab them from far away.
{% endhint %}

{% hint style="info" %}
In prior versions of Zoe for Unity, the 'Desktop Camera Control' component was named 'Desktop Controller' and needed to be added manually. This process is not needed anymore.
{% endhint %}


# Testing with a headset

Use your VR headset to playtest your experience.

{% embed url="<https://youtu.be/rHitjvGyD3M>" %}


# Navigation modes

To enable the user to navigate inside your scene you first need the camera to be converted into an Interactive Rig (see [previous step](/getting-started/interaction-rig)). Select the InteractionRIg(IO) and in the Inspector check the navigation option then choose the system you want. We currently offer two navigation systems: the **Teleportation system** and the **Joystick free navigation.**

<figure><img src="/files/MmRf74FlqvtRUszx4jwd" alt=""><figcaption><p>Navigation options</p></figcaption></figure>

## Joystick Navigation

User moves forward, backward, left and right by simply pushing the joystick in the same directions. You can choose the speed of navigation:

<figure><img src="/files/UVoGUzun4LFD5O2x0zjn" alt=""><figcaption><p>Joystick navigation settings</p></figcaption></figure>

## Teleport Navigation

Teleportation allows the user to select a nearby spot and be ported there as if they had jumped in no time.<br>

By default, the Teleport button is the **joystick** of the controller. Users first need to press and hold ‘up’ while aiming at the floor for the teleport beam to show up. When teleporting is possible, a circular target appears on the surface at the end of the beam. With the thumb, users can now turn the **joystick** (or the trackpad) to orientate the target position they will appear. Finally **release** to teleport to that spot.

Teleport has several settings that you can change at will.

<figure><img src="/files/VtL7UxPdkLlAeaoxxOsu" alt=""><figcaption><p>Teleport settings</p></figcaption></figure>

* **Controller for teleporting**: choose between Left/Right or Both controllers.
* **Teleport Distance** : maximum distance (meters) the beam reaches around the user.
* **Teleport Height**: maximum height (meters) for the beam.
* **Orient on Teleport**: allow the user to choose the orientation when they are going to teleport to a spot.
* **Hold Duration**: time (seconds) the user needs to hold the Joystick/trackpad for the beam to appear.
* **Input Sensitivity**: threshold for detecting user’s input on the Joystick/trackpad to launch a teleporting.
* **Pause Time**: time (seconds) to wait between each teleporting movement.
* **Teleport Target**: visual at the end of the beam when a teleport surface is reached. Note: we recommend not to change this.
* **Allowed/Not Allowed Destination**: color for the beam depending on the surface that is being aimed. Note: only surfaces (colliders) that are under the ‘Teleport’ Layer are considered allowed destinations.
* **Line Width**: width in meters of the beam.
* **Line Material:** material for the beam. Note: we recommend not to change this.

{% hint style="info" %}
For teleporting to a surface you need the mesh to be placed under the ‘Teleport’ Layer from Unity and make sure there is a collider of the shape of your surface.

Zoe provides a Floor prefab that you can directly add to your scene from the Zoe top bar menu.
{% endhint %}

## Camera Rotation

For both the **Teleportation** and the **Joystick** systems there is an option to rotate the camera as well with the controller.

<figure><img src="/files/v238yp2pQEUNEAhDtlNW" alt=""><figcaption><p>Camera Rotation Options</p></figcaption></figure>

Set it with the following options:

* **Left/Right/Both** joystick(s): controller to be used for the rotation; make sure you choose an option that matches with the one for movement.
* **Angle**: the angle (degrees) the camera is rotated at every input.

{% hint style="info" %}
If you don't have a headset or simply want to test/debug without it simply add the 'FPS Camera Controller' component to the Interaction Rig. Use WASD and mouse to interact.
{% endhint %}


# Overview

Zoe provides an easy-to-use interface to add interactivity to a 3D scene in minutes. It is a visual way of programming behaviors. Two main elements make this possible:

* [Interactive Objects:](/adding-interactivity/interactive-objects) any asset in the scene that you want to be interacted with needs to be converted into an interactive object.
* [Interactions:](/adding-interactivity/interactions) interactions are the base element of the programming system. They set behaviors for Interactive Objects by detecting **conditions** and triggering **actions** accordingly.

{% embed url="<https://youtu.be/1LanedqWTVw>" %}


# Interactive Objects

Zoe programming system uses what we call ‘Interactive Objects’ shortened hereafter **IOs**.

IOs are any object you want to add **life** to. Only an IO can use the **interaction system** of Zoe. IOs can be 3D objects, 2D objects, or any other object within your Unity scene. For instance, you can create a simple cube in Unity and convert it to an IO or you can import a model in Unity from your favorite 3D modeling software and convert it to an IO. As soon as an object has been converted into an IO, you will be able to add interactions and interact with it in VR.<br>

<figure><img src="/files/psibqtVGVyoaTpLOAXSe" alt=""><figcaption><p>An 'interactive apple'.</p></figcaption></figure>


# Creating IOs

To convert an object into an [IO](/adding-interactivity/interactive-objects), there are two options:

* **Right click** on your object in the Hierarchy view and chose: **Zoe > Convert Into Interactive Object.**

<figure><img src="/files/impNBu7OfgLG6duZGR1i" alt="" width="375"><figcaption><p>Convert with contextual menu.</p></figcaption></figure>

* **Select** your object in the hierarchy or in the scene view and in the menu bar select **Zoe > Convert > Into Interactive Object**.

<figure><img src="/files/y9Jij2oJyje7q9RNKr9i" alt="" width="289"><figcaption><p>Convert with top bar menu.</p></figcaption></figure>

A new object is created with an (IO) extension at the end and a specific structure inside.


# Structure of IOs

When you create an Interactive Object (IO), a new structure is generated from it in the Hierarchy panel of the scene:

<figure><img src="/files/6apU4R8fTzVF3BfE7AmR" alt=""><figcaption><p>IO Structure</p></figcaption></figure>

* **Interactions**: list of interactions defined by the user. You can add as many interactions as needed for each Interactive Object. To add a new interaction, just duplicate the “empty” one and rename the new interaction you created.
* **Visuals**: List of user’s visual assets defining the visual aspect of this IO. Visuals can contain any number of 2D and/or 3D asset(s). This is where the base asset can be found after converting it into an IO.

{% hint style="info" %}
*Note: You can also leave the Visuals empty, just keep the 'Visuals' node and use the IO as a trigger zone like a checkpoint, an invisible button, or simply a Manager object assigning behaviours to other objects in your scene.*
{% endhint %}

* **Proximity:** this collider defines the zone around the IO that is going to detect proximity with other objects. Used for the 'Proximity' condition

  Each IO has a proximity collider. It is up to you to define its shape, position and size. By default, we provide a simple box collider but you can replace it with any collider type as long as ‘Is Trigger’ is checked.
* **Gaze:** this collider defines the zone of the IO reacting to the user’s gaze (camera forward direction). Used for the 'Gaze' condition.

  It is up to you to define its shape, position and size. By default, we provide a simple cube but you can replace it with any shape as long as ‘Is Trigger’ is checked.
* **Hand Hover**: this collider defines a zone around the IO detecting the controller raycast. Used for the 'Point and Click' condition.

  It is up to you to define its shape and size. By default, we provide a simple box collider but you can replace it with any shape as long as ‘Is Trigger’ is checked.
* **Manipulate**: this collider defines the zone around the IO allowing to manipulate it.

  It is up to you to define its shape and size. By default, we provide a simple box collider but you can replace it with any shape as long as ‘Is Trigger’ is checked. In general this zone matches the shape of the object.
* **Snap Left/Right:** these transform objects (a position in 3D space) define the position and rotation the IO will take when grabbed by the user’s 'hands' (controllers).

  It is up to you to define their position and rotation


# IO Setup

Select your newly created [IO](#creating-ios) and go to the Inspector window. Here you’ll find the **Interactive Object Setup** section where you can change different parameters for your IO:

<figure><img src="/files/vxFE700Z1YYTb1yTa7v6" alt="" width="375"><figcaption><p>IO Setup</p></figcaption></figure>

* **Affected by Gravity: c**hoose if you want your object to be affected by gravity or not. If you want more physics options you can also change the settings of the Rigidbody component which is below in the hierarchy.
* **Enable Manipulation**: Choose if you want the user to be able to manipulate the object in the experience.
  * **Minimum distance**: Distance in meters from which the user can manipulate the object.
  * **Manipulation Mode**: Each Interactive Object has three manipulation options which you will find at the root :
    * **Grab**: Object can be grabbed by the user. You can define here the Grab Distance (minimum distance from which the user can aim and grab the object).
      * Attraction Speed (the speed the user will have when attracted to the hand).\
        ***Warning: speed needs to be at least 3 for the object to actually be grabbed.***\
        If the 'Snap on Grab' option is checked, the object uses the right and left Snap handles to position itself when grabbed.
    * **Point & Click**: the object detects when the user points at it and presses the trigger .
    * **Levitate**: The object can be moved at a distance with a levitation effect. This is particularly useful for experiences where there is less freedom of / no virtual movement (MR for example).
  * **Drag & Drop**: Drag and Drop is a system that allows IOs to have other objects as targets inside the scene where they can be snapped/dropped inside. This is useful when you need the user to place an object at a specific location.\
    To see how the system works check the Drag\&Drop section.


# Interactions

An Interaction defines the behaviour of an IO. Inside the ‘Interactions’ section of any IO, there is an **empty interaction** item. We recommend keeping it as-is and duplicate it to create new interactions. You can have as many interactions as you want inside an IO.

## Principle of an interaction

An interaction is composed by two fundamental elements:

1. A set of **Conditions**
2. A set of **Actions**

<figure><img src="https://www.zoe.com/wp-content/uploads/2020/02/interaction-principle.png" alt=""><figcaption></figcaption></figure>

The principle is simple: for any interaction, once its conditions are validated, the defined associated actions will take place.&#x20;

{% hint style="info" %}
Note: if you don’t define conditions but only actions, they will occur instantly, at start.
{% endhint %}

Let’s see how it works !

*Note: if you haven't already create an Interactive Object in your project, read* [*this*](/adding-interactivity/interactive-objects) *first.*


# Interaction Setup

First you need to decide when your interaction will happen. In the Hierarchy view, if you select the default interaction you will see the Interaction Setup in the inspector panel. This is where you set up when your interaction will be **active**.

<figure><img src="https://www.zoe.com/wp-content/uploads/2020/05/InteractionScript-1.png" alt=""><figcaption></figcaption></figure>

Each Interaction of an Interactive Object has 3 distinct phases:

* **Active:** after delay and dependencies (if any) are met.\
  *Note that an interaction can be deactivated and reactivated again, and that once activated it can repeat itself (see details in sections below).*
* **Triggered:** when conditions are met.
* **After:** after the interaction is triggered (before being active again if it’s the case)

You can set your interaction with the following options:

* **Dependencies:** allows you to define if this interaction is dependent on any other interaction from the scene in order to be active. It takes into account the moment an interaction triggers. If **‘Require All’** is checked, all the interactions in the list must be triggered in order for this interaction to become active. If not, as soon as one of them triggers then the interaction becomes active.\
  This will allow you to build chains of events inside your experience.  Whether it is to build an interactive story, game mechanics, tutorials or simulations, dependencies are a practical and simple feature.
* **Delay:** time before activating the interaction. Note that if your interaction has Dependencies, the delay will start after the dependencies are met. If no dependency is set the delay will start at the beginning of the experience.
* **Repeat:** by default an interaction only happens once. Here you can set your interaction to repeat (either a limited number of times or infinitely).
  * If **“Check Conditions Only”** is selected then it means that as soon as the conditions are met again, the interaction will trigger again.
  * If **“Check Conditions & Dependencies”** is selected then it means that not only conditions need to be met but also dependencies have to be validated (again) in order for the interaction to trigger again.
  * The **‘repeat delay’** allows you to set a waiting time between each iteration of the interaction.\
    **IMPORTANT:** make sure to add a delay (at least 0.3s) when repeating an interaction if another one is also repeating and is linked to the first one (same condition / dependent on).

Once your interaction is setup you can now define the behaviour you want your IO to have by adding **conditions** and **actions**. To add a condition or an action to your interaction, click on the ADD CONDITION or ADD ACTION dropdown menus at the bottom of the **Interaction Setup**.

<figure><img src="https://www.zoe.com/wp-content/uploads/2020/03/AddCondition-1.jpg" alt=""><figcaption></figcaption></figure>


# Conditions

Conditions are incidents that need to be fulfilled for an action to occur. They can also be called ‘triggers’. You can add as many conditions (same or different) as you need inside a single interaction. Action(s) will happen only when all conditions of an interaction have been fulfilled.


# Duration (parameter)

**Duration** is an option available for almost all conditions, allowing to set a "wait time" until the corresponding condition becomes valid (instead of becoming valid instantly).&#x20;

{% embed url="<https://youtu.be/0xPFjjTUCjA?si=DoeGxgXXaRKM74e3>" %}

If you set up a `minimum duration required` it means that the given condition needs to remain true for this amount of time in order for the condition to be considered valid.

Example: the user needs to look at an object for at least 2 seconds in order for a door to open.

{% hint style="info" %}
*If you have multiple objects in your condition, then the duration time is required for each one of them in order to validate the condition.*
{% endhint %}

**If condition turns false:** here you decide what happens if during the duration time the condition turns false.

* **Reset count:** the count is reset to 0.
* **Keep Progress:** The amount of time the condition remained valid is kept in memory and if condition is true again then it accumulates until it reaches the duration time.
* **Decrease progressively:** the count decreases progressively with a speed factor.

These options are useful for game mechanics where you want the user to fulfill something for at least a given amount of time to progress/win. If the user does not, then you decide if the progress is kept in memory or not.


# Gaze

Gazing at an object in VR is pretty much the same as looking at an object in the real world. The **Gaze** condition checks if the user is looking at a specific IO.

{% embed url="<https://youtu.be/XTRQVVQYT1o?si=9vNiE7YG3-OaHwtG>" %}

The condition includes the following parameters:

* **Target Object**: the object (IO) you want to check if the user is looking at or not.
* **Mode:** if Mode is set to `Gaze_At`, it means the user looks at the object. If Mode is set to `Gaze_Away`, it means the user looks away from the object. \*
* **Minimum duration required:** check details [here](/adding-interactivity/interactions/conditions/duration-parameter).

{% hint style="info" %}
The Gaze condition uses the Gaze Collider of the Target IO (it checks if the raycast coming from the camera is colliding with this collider).
{% endhint %}

{% hint style="info" %}
`Gaze_At` is not detected if at the moment the interaction is active and checks the condition the user is already looking at the IO.
{% endhint %}

<br>


# Point and Click

This condition checks if the user is pointing at a specific [IO](/adding-interactivity/interactive-objects) with the controllers. **Make sure your Target Object has ‘Point and Click’ enabled as Manipulation mode.**

* **Point + trigger**: allows you to check if the user is just pointing (like hovering) or pointing **AND** triggering at the same time (user presses trigger button).&#x20;
* **Hand:** choose the hand you want to take into account (`EITHER`, `LEFT` or `RIGHT`, and `BOTH` if ‘+Trigger’ is not required in the condition)
* **Mode:** If Mode is set to `Point at` it means the user needs to point to the specified IO (and trig if `Point+trigger` is checked). If Mode is set to `Point Away` or `Release` it means the user needs to point away from the object (and/or simply release the trigger).
* **Target Object(s):** the object(s) IO you want to check if the user is pointing at or not. If you set several objects whenever one of them meets the condition it will validate it.\
  *Note: only IOs with “Point and Click” enabled at the root will be detected.*
* **Minimum duration required:** check details [here](/adding-interactivity/interactions/conditions/duration-parameter).


# Proximity

Proximity is the nearness in space between objects. The **Proximity** condition checks if (at least) two objects are near one from each other.

{% embed url="<https://youtu.be/-bk5S2L6FxI?si=ii76Bm8bIlnrozXR>" %}

The condition includes the following parameters:

* **Mode:** if you select `ENTER`, it means objects have to be **close from one another** at least at the specified distance (or below).\
  If you select `EXIT`, it means objects need to be far from each other, at a distance above than the distance set.
* **Max distance:** distance, in meters, between objects for the condition to be valid. Objects should be either at this distance or below to validate the`ENTER` or be above to validate `EXIT`.

*Note that the condition uses the Proximity colliders of the given IOs , the distance is calculated from the center of each collider but you can choose to calculate from the edges.*

* **Objects in proximity:** objects ([IO](/adding-interactivity/interactive-objects)) that need to be in proximity (at least two). You can add more than two objects, then if `Require All` is checked, all the specified objects in this list are required to validate the condition. If `Require All` is not checked, only one combination required for validating the condition.

**Minimum duration required:** check details [here](/adding-interactivity/interactions/conditions/duration-parameter).


# Touch

Touching an object in VR means placing your controller(s) on or into it. The **Touch** condition checks if the controllers are in collision with specific [IO](/adding-interactivity/interactive-objects)s.

{% embed url="<https://youtu.be/h6-UWfbeA5o?si=quGuEznvXHQV6WX5>" %}

The Touch condition includes the following parameters:

* **Hand:** choose which hand(s) must touch (or not) the specified object. It can be one of the four options: `Either`, `Left`, `Right` or `Both`.
* **Mode**: If you select `Touch`, then the specified hand(s)/controller(s) needs to be touching the specified object to fulfil this condition.\
  If you select `Untouch` then the specified hand(s) should not be touching the specified object anymore to fulfil this condition.\
  \*Note that `Untouch` requires the specified object and hand(s) to be previously in collision.
* **Target Objects:** target object(s) from the scene that the user needs to touch (or stop touching) for this condition to be met. You can have more than one object meaning that whenever one of the objects is in collision with the specified hand(s) the condition is valid.
* **Minimum duration required:** check details [here](/adding-interactivity/interactions/conditions/duration-parameter).

<br>


# Manipulate

The **Manipulate** condition checks if the user manipulates (grabs or levitates) an [IO](/adding-interactivity/interactive-objects).

{% embed url="<https://youtu.be/SHuEEymNJdg?si=2t5jXP9q9zGZPgd0>" %}

The condition includes the following parameters:

* **Hand:** choose which hand must manipulate (or not) the specified object. It can be one of the three options: `Either`, `Left` or `Right`. “Both” is not an option as you can not manipulate an object with both controllers at the same time.
* **Mode**: If you select `Manipulate`, then the specified hand(s)/controller(s) need to manipulate (grab or levitate) the specified object to fulfil this condition. If you select `Manipulate+Hold,`the condition will validate **if the object is already being manipulated.** If you select `Release` then the specified hand(s) should release the object to fulfil this condition. \
  \*Note that `Release` requires the user to previously manipulate the object.

{% hint style="info" %}
`Manipulate + Hold` is useful when you have another condition paired (for example a collision or a button to be pressed) so the user can hold the object and the action only triggers when the second condition is valid. Example: a flashlight that turns on when the user presses a button (while holding it).
{% endhint %}

* **Target Objects:** IOs from the scene that the user needs to manipulate (or release) for this condition to be met. You can have more than one object meaning that whenever one of the objects is manipulated, the condition is valid.
* **Minimum duration required:** check details [here](/adding-interactivity/interactions/conditions/duration-parameter).


# Inputs

The **Controller Inputs** condition checks if the user is using any input (button, trigger, stick,...) from controllers.

{% embed url="<https://youtu.be/QLhOJLJezeM?si=0iZyVgtRKhcUbi-y>" %}

The condition includes the following parameters:

* First choose the controller: `RIGHT` or `LEFT`
* Then choose the specific button (see figure below for details)
* Finally choose the state of the button you want to check: `TOUCHED`, `UNTOUCHED`, `PRESSED`, or `RELEASED`

**Minimum duration required:** check details [here](/adding-interactivity/interactions/conditions/duration-parameter).

<figure><img src="/files/IwgUoGJfrxaZfZj2YYBO" alt=""><figcaption></figcaption></figure>

Add as many inputs you want to check, and decide whether the condition needs for all of the inputs to be used (`Require All`) or not for the condition to be valid.


# Drop

The **Drop** condition is available for [IO](/adding-interactivity/interactive-objects)s with the Drag & Drop system enabled.

This condition checks in which phase of the Drag & Drop a given IO is at.

* **Object:** IO that is being manipulated to be dropped.
* **Mode**
  * `Drop` = object has been dropped on the target
  * `Ready to drop`= object is close enough from target to be dropped
  * `Cancel drop`= object is taken away out of the minimum distance from target
  * `Remove` = object has been removed from target
* **Target(s):** drop targets that need to be checked.


# Approach

The **Approach** condition allows to set up a zone around interactive objects to launch actions when the user enters it.

{% embed url="<https://youtu.be/faEy2mU128Y?si=PTlmUnc4rMw48P6Q>" %}

The Approach condition includes the following parameters:

* **Approach** **Mode:** if you select `ENTER`, it means the user has to be close from the object(s), at least at the specified minimum distance.\
  If you select `EXIT`, it means user needs to be far from the object(s), at a bigger distance than the minimum distance set.
* **Distance:** distance, in meters, between the user and the object(s). Objects should be either at this distance or below (to validate`ENTER`) or be at a bigger distance (to validate `EXIT`).

{% hint style="info" %}
*Note that the condition uses the Proximity colliders of the given IOs and you can choose if the distance is calculated from the center of each collider or from the edges* (using the checkbox below the distance).
{% endhint %}

* **Objects in proximity:** objects ([IO](/adding-interactivity/interactive-objects)) that the user needs to approach. You can add more than one, then if `Require All` is checked, all the specified objects in this list are required to validate the condition. If `Require All` is not checked, only one of the objects is requires for validating the condition.
* **Minimum duration required:** check details [here](/adding-interactivity/interactions/conditions/duration-parameter).


# Collision

**Collision** is when at least 2 objects collide.

* **Collision Mode:** if you select `ENTER`, it means objects have to be **in collision** with each other to validate the condition. If you select `EXIT`, it means objects need to **stop colliding** for the condition to be valid.
* **Target Object(s):** select at least 2 objects that need to be colliding (or not). If several objects are set it means whenever two of them collide (or stop colliding) the condition will validate.
* **Minimum duration required:** check details [here](/adding-interactivity/interactions/conditions/duration-parameter).

{% hint style="info" %}
*Note that the condition uses the **Proximity colliders** of the given IOs.*
{% endhint %}


# Actions

Actions are the behaviors triggered by the fulfilment of conditions. Actions occur only if all conditions of an interaction have been triggered, or immediately at start if there isn't any condition set in the interaction.


# Delay (parameter)

Available inside every action, the `Delay` parameter adds a delay for the action to happen **after** the conditions have been met (the interaction will be triggered but the action will wait until the delay is finished).

*Example: an interaction is set with a 'Touch' condition on a button and an 'Audio' action with 2 seconds delay to play a sound. When the user touches the button, the audio action waits 2 seconds before playing the sound.*


# Scale

The `Scale` action Allows to modify an object’s size with the following parameters:

* **Object(s) to scale:** list of objects you want to scale up/down.
* **Scale mode:** two ways of setting a new scale are available:
  * **Absolute scale:** the object(s) scale will match the new values.
  * **Scale factor (scale mode):** the object(s) current scale will be multiplied by the new values.
* **Time \[s]:** time in seconds for the scale transition.
* **Back & Forth:** does the action and reverts it once.
* **Loop:** does the action in loop.


# Rotate

The **Rotate** action allows to rotate objects on one or several axes.

{% embed url="<https://youtu.be/Gn9LVmFYrDE?si=8uOmCXGKaLwXD3kh>" %}

The Rotate action includes the following parameters:

* **Object(s) to rotate:** List of objects you want to rotate.
* **Rotation angle(s):** angle value you want your object to rotate around each of its axes.
* **Time \[s]:** time in seconds for the rotation transition.
* **Back & Forth:** does the action and reverts it once.
* **Loop:** does the action in loop.


# Rotate Around

This action has ‘sections’ allowing you to add several times the same action with different parameters every time. You can add as many sections you want. Each section allows to rotate objects around the axis of a pivot object with the following parameters:

* **Object(s) to rotate:** List of objects you want to rotate.
* **Pivot:** reference object from the scene you want your object(s) to turn around.
* **Rotation angle(s):** angle value you want your object(s) to rotate around each of the pivot’s axis.
* **Time \[s]:** time in seconds for the rotation.
* **Back & Forth:** does the action and reverts it once
* **Loop:** does the action in loop.


# Translate

The **Translate** action allows to move an object from its initial position to a specific target.&#x20;

{% embed url="<https://youtu.be/6FTP1XvoW2M?si=p4N-qrxmPpkt6Xfb>" %}

The Translate action includes the following parameters:

* **Object(s) to move: l**ist of objects you want to move.
* **Destination:** objects from the scene (any Transform) you want your object to move to.
* **Consider rotation:** makes the object match the destination’s orientation.
* **Parabola height \[m]:** an effect of parabola can be added to the movement,  you define the height of the parabola the object will reach while moving towards the new position.
* **Number of Flips:** number of flips you want your object to do when moving towards the new position. Usually flips are combined with a parabola effect.
* **Offset \[m]:** it defines the distance at which the object must remain from the target when moving.  Useful when you want an object to move towards another one but not bump into it.
* **Duration \[s]:** time in seconds for the moving transformation to happen.


# Activate

This actions allows you to **activate and/or deactivate** objects from your scene.

* **GameObjects to Activate:** any object from the scene that you want to activate.
* **GameObjects to Deactivate:** any object from the scene that you want to deactivate.


# Audio

The **Audio** action allows you to trigger any action related to audio.

{% embed url="<https://youtu.be/YZ8afUQvtQU?si=n1rBpluc9Hy6pNWd>" %}

The Audio action includes the following parameters:

* **Action:** `Play`, `Stop`, `Pause` or `Mute` an audio.
* **Audio source:** by default here you have the Audio Source of your root (IO), however if you want to choose another one (maybe you have more than one Audio Source or you have objects inside with their own Audio Source), just drag it here. To read about Audio Sources, click [here](https://docs.unity3d.com/Manual/class-AudioSource.html).
* **Volume:** define the volume of your audio (value ranges from 0 to 1).
* **Loop:** for a single clip it will play it in loop, for a list of clips you can choose to loop the **whole list** or loop only **the last clip** after playing the whole list.
* **Playlist:** set here how to read a list of clips, either in the **order** they were added or in a **random** order.
* **Fade In:** check this if you want your clip to fade in at the beginning.
* **Fade Out:** check this if you want your clip to fade out at the end.
* **Change pitch:** check this to change the pitch of your clip using a slider with values from 0.5 to 3.


# Animation

The **Animation** action allows you to trigger an animation. This action is using the **Animator** component from Unity. It means that any animation clip you want to play needs to be inside an **Animator Controller** and your object needs the **Animator component** attached. For details on how to set your Animator Controller, read the next section below.

* **Action:** `Play` an animation or `Disable` an animator.
* **Animator:** here you need to drag the Game Object from your scene that has the Animator Controller attached.&#x20;
* **Trigger:** Here you have the list of all ‘trigger transitions’ found in the specified Animator Controller.\
  *The action reads the transition between clips from an Animator controller and the only type of transition read by this action is of type ‘Trigger’. To read a clip make sure you set a ‘Trigger’ condition on the transition.*

### Setting up an Animator Controller

To launch animations with Zoe for Unity you need to set up an **Animator** with the animations you want. An animator controller works as a ‘State Machine’ where every animation clip is a state of your object and there are transitions between the states, sometimes with conditions. For example, for a cat you could have the following states: **Idle** (cat is seated and moves its tail a bit), **Walk** (cat walks) and **Meow** (cat is meowing). Then you need conditions to go from one state to the other. The condition type that Zoe reads is the ‘Trigger’ one, the one you need to set in order to read the animations with the Animation Action. For this cat example, you would create a Trigger transition called **CatWalks** and **CatMeows** and you would set them in between states, targeting the Walk or the Meow state.

The animations or states of your animator can be either created in Unity or in a 3D animation software. Here are the two options on how to set your controller depending on the source of the animations:

* **Using external clips:** if you created your animations on a separate software then you need to import them embedded in your 3d model. FBX is the best and most suitable format to do this.\
  Inside Unity you need to create an Animator Controller that you will attach to your object.

<figure><img src="/files/5iZeNglgZk7v03KqJ6PP" alt=""><figcaption></figcaption></figure>

To set your controller you need to open the Animator Window, the easiest way is to double-click on the Animator Controller you just created. Here you need to drag the clips from your FBX file. They will appear as states of the Animator. Now set the clip you want to play by default, right-click on it and select “Set as Layer Default State” it will then be attached to the ‘Entry’ element.

<figure><img src="/files/xGrlvnf4EW1I6PTi6tu8" alt=""><figcaption></figcaption></figure>

Then you need to create transitions between all your clips and to assign a Trigger condition for each. For this, go to Animator > Parameters on the left side of the Animator window. Click on the ‘+’ sign and select ‘Trigger’. Then name it as you want (we recommend using the name of your target state so you know which type of clip is going to play).

<figure><img src="/files/GkS7F1mmKCFXJUA9mbzb" alt=""><figcaption></figcaption></figure>

To create a transition between two states simply right-click on the first state, select “Make Transition” and drag the arrow to the next state. Now select the arrow/transition and in the Inspector go to Conditions and add one (‘+’). Then in the list select the corresponding Trigger condition.

<figure><img src="/files/Yup6Ok7pyZvPJ0US8BGF" alt=""><figcaption><p>Transition Condition</p></figcaption></figure>

Finish setting up the Animator with all transitions and you are ready to use it in the interactions!

* **Using Unity animations:** you can animate your objects directly in Unity as well. For this select the object in the Hierarchy, then go to the Animation Window (open it if you don’t have it by default). Hit on ‘Create’, this will not only create an Animation Clip but also automatically an Animator Controller (named after your object).

<figure><img src="/files/eiRuQKpJH1LYwVoOTcO0" alt=""><figcaption><p>Animate inside Unity</p></figcaption></figure>

* Animate your object either by recording and moving by hand or by changing the values of different Properties inside the Animation window. For details on how to Animate with Unity, [click here.](https://docs.unity3d.com/Manual/animeditor-CreatingANewAnimationClip.html)<br>

For setting up your Animator follow the same steps (2-4) of the previous section “Using external clips”.

For learning in deep how to use Animators and how to animate inside Unity, click [here](https://learn.unity.com/search?k=%5B%22q%3AAnimation%22%5D).

<br>

<br>


# Physics

The **Physics** action allows to change the physic properties of an object.

{% embed url="<https://youtu.be/z9hfVt4OM4c?si=LV3Fdowd4X4-NYEz>" %}

The action includes the following parameters:

* **Target Object(s):** IO(s) you want to modify their properties of.
* **Affected by gravity:** change the object’s subjection to gravity.
* **Enable collisions:** enable/disable if the target object detects collision or not.\
  This action will act on the collider at the root of your IO.
* **Change mass:** assign a new mass (kg) to your object.


# Change Material

This action allows to change an object’s material.

{% embed url="<https://youtu.be/1ptUSTr8hAQ?si=4aji7BIlVQLZxZau>" %}

The action comes with the following parameters:

* **Delay:** See [Delay](/adding-interactivity/interactions/actions/delay-parameter).
* **Target Object(s):** Game Object you want the material to be changed.
* **New Material:** new material.
* **Time \[s]:** duration of the transition between materials.
* **Loop:** do the action in loop (you can use it if you also checked Back\&Forth)
* **Back & Forth:** alternates between the current material and the new one.


# Change Manipulation

The **Change Manipulation** action allows to modify the mode of manipulation of an object.

{% embed url="<https://youtu.be/VmjBDdHevps?si=RDVNEb0KD9a9vEPm>" %}

The action comes with the following parameters:

* **Delay:** See [Delay](/adding-interactivity/interactions/actions/delay-parameter).
* **New mode:** Select either Grab, Point & Click, or Levitat&#x65;**.**
* **Objects:** The Objects you want the manipulation mode to change.


# Vibrate

The Controller Vibrate action allows to add vibrations to your controller(s) in an interaction.

{% embed url="<https://youtu.be/9hzRzH-eY6k?si=bblf3Q5Yuc578eOy>" %}


# Fade Transition

The **Fade Transition** action allows to turn the screen to black between two different moments or two different scenes of an experience.

{% embed url="<https://youtu.be/OB_98awHcBw?si=GaD78axBSaBQpRGm>" %}


# Drag & Drop system

**Drag & Drop** is the ability to set a target place for an object to go into (in this example, the hat is dragged and dropped on the character’s head). This feature is extremely useful to define **snapping zones** for any type of experience if you want your user to place an element **at a specific spot**.

<figure><img src="/files/HxoIVO8Le0F1CwaQUPVD" alt=""><figcaption><p>Hat being 'dragged and dropped' on a target.</p></figcaption></figure>

Follow the steps below to setup the Drag and Drop for a given IO:

1. **Create an IO** that will be the object that is dropped inside a target (see the [Create Interactive Objects](/adding-interactivity/interactive-objects) section to know how to do it);
2. Check **Enable Drag And Drop** at the root of the Object;
3. Now you can setup the options.

{% embed url="<https://youtu.be/YCicxN5JmVI?si=u6b9jyFQz27CWDYa>" %}

## Drag\&Drop targets:&#x20;

* Choose among all IOs in the scene the target(s) for your object to be dropped on. You can have several targets for one object.&#x20;
* Alternatively you can generate automatic targets by entering the number of targets you want and clicking on the `GENERATE` button.\
  Automatic Drop targets have a Box Collider at their root by default. Make sure to remove it in order for the Drop to work.\
  **Warning:  in this version of the plugin, when a target is generated it will clone all the interactions you already have inside your object, so make sure to remove them or change them according to your needs.**

## Drop Requirements

Set here the requirements for how the user needs to place an object on a target in order to do a valid drop.

* **Min Distance for Valid Drop:** the distance between the drop object and the drop target. If not within this distance, the drop is not allowed.
* **Match orientation on X/Y/Z Axis :** check these if you want the drop object to match the orientation of the drop target (choose among axis) in order to allow the drop.&#x20;
* **Allow mirror:** this option is available if an axis is mandatory. It allows you to validate the drop if the object matches the axis orientation both in positive and negative directions. This is useful for objects that don’t necessarily have a front/back, objects that are symmetric like a cylinder, etc).
* **Angle Threshold:** represents the precision in which the orientation of the drop object on the drop target should be as a percentage. I.E. if the threshold is set to 100 it means the object needs to match at 100% the axis orientation. This is useful for setting the level of difficulty to the user when dropping an object into a target.

## Drop Parameters

* **Allow drop on occupied targets**: allow to drop an object on a target even if another drop object is already there.
* **Lock after dropped:** lock the object at the target position when it has been dropped.
* **Snap on drop:** snap into target’s position when object is dropped.
* **Time to Snap:** duration in seconds of the transition for the drop object to match the target position when the user releases it into the target.

<br>


# API - Custom Scripts

Zoe has a modular structure allowing you to create your own scripts in combination with the whole system. This is possible thanks to an API inside the package in which actions and conditions are actually programmed.

There are two templates provided in Zoe allowing you to create custom conditions and actions. Check the following pages for the details.

<figure><img src="/files/D5fpkQI5CYiyKFpfGL1B" alt=""><figcaption><p>Custom Action Template</p></figcaption></figure>


# Create your own Condition

Find the script **TemplateCondition** in your Project window (under **Scripts > Interactions > Conditions**) duplicate it and rename the duplicated file with your condition name \[YourConditionName]. Once this is done, open the file for editing.

Rename the class name from:&#x20;

```
public class TemplateCondition : S_AbstractCondition
```

to:

```
public class [YourConditionName] : S_AbstractCondition
```

{% hint style="warning" %}
**IMPORTANT: the name you gave to the file and the name of the class need to be the same.**
{% endhint %}

The whole logic of a condition revolves around calling the ***Validate*** function to tell the system your condition has been validated. Outside of the functions you see in the template, you will need to implement your own logic that will call ***Validate*** based on some requirements you defined.

You also need to fill up the three functions ***Setup***, ***Dispose*** and ***Reload*** with logic.

***Setup*** will be called before your condition is actually checked for validation. Use this function to prepare the things required for its validation.

***Dispose*** is basically the opposite of ***Setup*** and undoes what was done in setup so that the condition does not accidentally validate again.

Typically the ***Setup*** and ***Dispose*** are usually called in a loop if your condition is reloaded several times.

***Reload*** can have some custom logic of your choosing, but it is usually solely made for calling ***Invalidate*** which simply tells the system the condition is now ready for validation again.

You can then use your custom CONDITION inside any *Interaction* through the ***Add Component*** menu.


# Create your own Action

We explain here the basics of implementing a new Zoe ACTION with your own code:

Find the script **TemplateAction** in your Project window (under **Scripts > Interactions > Actions**) duplicate it and rename the duplicated file with your action name \[YourActionName]. Once this is done, open the file for editing.

Rename the class name from:&#x20;

```
public class TemplateAction : S_AbstractAction
```

to

```
public class [YourActionName] : S_AbstractAction
```

{% hint style="info" %}
**IMPORTANT: the name you gave to the file and the name of the class need to be the same.**
{% endhint %}

You can then code what you want to happen when the action triggers inside the ***ActionLogic*** function where the comment says *‘Implement your action logic here’.*

You can then use your custom ACTION inside any *Interaction* through the ***Add Component*** menu.


# Multiplayer

Implement multiplayer experiences using our Network Module.

Zoe allows you to create interactive experiences connecting multiple users in a 'session'. For this we provide an integration of the [Photon Unity Networking (PUN)](https://doc.photonengine.com/pun/current/getting-started/pun-intro) framework compatible with Zoe's core system. Base networking classes contained in the base Plugin package will only work if you also install the Networking Module.

Here's what you will need to be able to build multiplayer experiences:

* Zoe for Unity (verify that the version is compatible with the module)
* PUN Realtime and PUN Voice (plugins for Unity)

Follow the next steps for a detailed installation and how to use the networking features.


# Installation

How to install Zoe Networking Module

Make sure you have previously [downloaded and installed](/installation/installing-zoe-for-unity) Zoe for Unity plugin.

Download the Networking Module (compatible with the version of Zoe for Unity that you previously installed).

With your Unity project open, double-click on the .unitypackage of the module. You should see the following window:

<figure><img src="/files/Vn4vjgWLFKuir5V37XZp" alt=""><figcaption><p>Networking Module importing window</p></figcaption></figure>

Press on 'Import', the following window should pop up:&#x20;

<figure><img src="/files/LXpsGW9z5BfUe2vMOdfA" alt=""><figcaption><p>Neworking Module Installation Popup</p></figcaption></figure>

Before installing the Zoe module you will need to install Photon. You can use both buttons in the popup window or click on the following links:

* [PUN 2 Realtime (free)](https://assetstore.unity.com/packages/tools/network/pun-2-free-119922):  allows to connect users in a session.
* [PUN Voice 2 (free)](https://assetstore.unity.com/packages/tools/audio/photon-voice-2-130518):  allows users to communicate via voice during a session.

{% hint style="info" %}
Note that you could also install both Photon packages in your project before opening the networking module.
{% endhint %}

Open both plugins in Unity, you should see the Package Manager window open:&#x20;

<figure><img src="/files/B3IsEjHuQUCy8f18JSzI" alt=""><figcaption><p>PUN packages inside Unity</p></figcaption></figure>

Download both Photon packages into your project.

{% hint style="info" %}
Before importing the Photon packages you will need to close the Zoe Networking module initialization popup window (otherwise the Import window for the packages won't show).
{% endhint %}

Import both Photon packages into your project (you might need to close the Zoe initialization popup every time). This is what you should see when importing the Photon PUN package:

<figure><img src="/files/0ABOQrzu7kOoD1yZ2JKT" alt=""><figcaption><p>Import popup window for Photon</p></figcaption></figure>

While importing Photon PUN 2 you will get a popup to fill in the Photon Settings, you can skip this to fill later or follow the project Setup if you already have a Photon account and application details. This will be required for distributing your application.

<figure><img src="/files/hSbfWLZzc6jmzB3RvPTk" alt=""><figcaption><p>PUN Setup popup</p></figcaption></figure>

After packages have been imported, go to the Zoe menu on the top bar and click on 'Open Initialisation Tool'. This should open back the Networking Module popup window. Finally click on **'Install Zoe Photon Integration'** and wait until the process is finished. Once you're done you should get the following Folder structure in your project:

<figure><img src="/files/nhVslG4zGRIOqNybLCMF" alt=""><figcaption><p>Folder Structure with Networking Module</p></figcaption></figure>


# Photon Setup

Photon application settings

As mentioned previously you will need to fill some information for Photon to work and to distribute your final application.&#x20;

Either you setup your project while installing, either you fill the Photon Server Settings afterwards, by going to *Window > Photon Unity Networking > Highlight Server Settings*:

<figure><img src="/files/QvzotdSpsl7PKHrIENgj" alt=""><figcaption><p>Photon Server Settings</p></figcaption></figure>

The only required fields for your experience to work are the Photon Realtime and Voice App Id's. For this you will need to create an account in Photon with an Application in both Realtime and Voice. Here are more details on how to set Photon in your project: <https://doc.photonengine.com/pun/current/demos-and-tutorials/pun-basics-tutorial/intro>


# Scripting Symbols

One last step is required for Photon integration to work properly. You may see some errors in the console after installing the Networking Module. To fix them, go to *Player Settings > Other Settings > Scripting Define Symbols*, and add two new lines:

```
PUN_2_0_OR_NEWER
PUN_2_OR_NEWER
```

This is how your setting should look like:

<figure><img src="/files/7Fc8pMs3Qx4UETklCOJJ" alt=""><figcaption><p>SCRIPTING DEFINE SYMBOLS</p></figcaption></figure>


# Get Started

In order to transform a scene into a networked scene you simply need to add the 'PhotonNetworkManager' prefab.  For this you can either find it and drag it in the project or you can go to *Zoe> Networking > Create Networking Manager* on the top bar menu:&#x20;

<figure><img src="/files/3se2guyvVJzbK5BSLnrT" alt=""><figcaption><p>Add a Networking Manager to a scene</p></figcaption></figure>

In the Inspector you will see the following script which contains the settings for a multiuser session:

<figure><img src="/files/zQBnR6LcNmFQCUcktI7e" alt=""><figcaption><p>Networking Manger Settings</p></figcaption></figure>

* **Max Player Count:** set the number of users that can join the same session (maximum is 16, this is set by Photon framework)
* **Group Players:** check this to create groups of players into different Photon rooms (sessions) when you build the same experience. For this you can provide a different GroupID for each build.

{% hint style="info" %}
Note that grouping players is the only provided option to have players split in different sessions. The system currently opens a session right at the start so **anyone** launching a build of your experience will automatically join the session.

A system of code exists in the background but interfacing will be provided only in a future version of this networking module. If you want users to connect via codes you will have to implement the system and itnerfaces yourself.
{% endhint %}

* **Avatar settings:** Zoe provides a basic avatar system with heads, hands and accessories. You can either choose the default provided avatars (Zoe Avatars) or use your own 3D models (Custom Collection). *'Color strategy'* allows you to either have a random color assigned to each new avatar joining the session, or to keep all avatars with a single color. For more details, check the [Avatars page](/multiplayer/avatars).

Another useful component from the Manager is the **Spawn Point Container**:

<figure><img src="/files/TMxcESPHTs9IwFZ978o7" alt=""><figcaption><p>Spawn Point setup</p></figcaption></figure>

Spawn points are Transforms (positions) where the users will pop when joining a scene. If this option is not checked any new user joining will pop at the 0,0,0 position. \
If you want to set specific locations for the users to start the experience you need to create or provide Game Objects to be assigned in the list of Spawn Points (as shown above). The system will use the spawn points in the order provided for each new user, one after the other.


# Avatars

Options to represent users in your multiuser experience

The networking module provides a simple avatar system for representing users in a multiuser session. Inside the Networking Manager you can choose to use Zoe Default avatars or use your custom 3D models, through a 'Custom Collection'. Both use a 'Color Strategy' allowing to assign either a random color for each new avatar or a single one to all.

### Zoe Avatars

These are the default avatars from Zoe, you can also find them in the standalone application. The 'color strategy' is applied to the head, and accessories vary randomly:

<figure><img src="/files/OH3rvDvpBDZA1MJ6TqyI" alt=""><figcaption><p>Example of Zoe Avatars in a session</p></figcaption></figure>

* To see all the 3D models available, you can check the Avatar Prefab Collection inside *Network > Zoe Avatars*

### Custom Collection

Choose this option to use your own 3D models or a variant of the Zoe one. You will see the following options in the Inspector:

<figure><img src="/files/e8eeOm11NgCRd5fVB1sg" alt=""><figcaption><p>Custom Collection parameters</p></figcaption></figure>

Here you can either create a new collection or copy the Zoe default one and modify it as you wish. A prefab collection looks like this:

<figure><img src="/files/A8z6W76S6tAIm2t3EkBX" alt=""><figcaption><p>Avatar Collection with elements to fill</p></figcaption></figure>

\*Hats are accessories that will show on top of the heads.

{% hint style="info" %}
Note that elements will be mixed and matched randomly.
{% endhint %}

In order for the system to work, you will need to assign a specific script to every element. Make sure you add the following scripts to their corresponding avatar part:

* Avatar Head
* Avatar Face
* Avatar Hat
* Avatar Left and Right Hand

### Color Strategy

When using your own 3D models you can also choose the specific 3D parts that will be affected by the 'color strategy'. As you will notice inside every specific script you can choose the 'Colorable parts':

<figure><img src="/files/kkkGZQ6xfi1t5D0cH3ru" alt=""><figcaption><p>Customising how Color Strategy is applied to 3D meshes</p></figcaption></figure>

For each element you can:

* Assign a ***Mesh Renderer***
* If your mesh has multiple *Materials* assigned you can indicate the one you want to be modified by indicating its Index (make sure you choose ***RendererWithIndexColorable*** in this case)
* Shader Property: change this if you are using custom shaders (and you know about shaders ;) ) and would like to modify another property than the ***\_Color*** one.
* For the **Head** you can also specify the anchor points for the accessories (hats) and the face element.


# Multiplayer Conditions

When adding the networking module to your project, you will see new conditions available in the list when setting an interaction:

<figure><img src="/files/PT6IDdt4d765s2R7aijR" alt=""><figcaption><p>Added Conditions for multiuser experiences</p></figcaption></figure>

#### Approach Multiplayer

This condition works as the normal ['Approach'](/adding-interactivity/interactions/conditions/approach) condition but allows to set a minimum number of players that must meet the condition for it to be actually validated.

This is useful to trigger actions only when a given amount of players are near an object, or are inside a perimeter, have reached a checkpoint etc.

#### Players In Session

Allows to detect when the number of players in the sessions is '*less than', 'equal'* to or '*more than' a* given number for you to se&#x74;*.*

Useful to know when you have reached the minimum or maximum number of players to start an experience, or if there are not enough players to continue the experience etc.

#### Player Joined or Left

Allows to know when a user has joined or left a multiuser session.

Check 'For Local Player' if you want the condition to be valid when the current player joins/leaves.

Useful to give feedback (sound for example) to users.


# Multiplayer Actions

When adding the networking module to your project, you will see new actions available in the list when setting an interaction:

<figure><img src="/files/TFm6foLpq90SdE9Db1ij" alt=""><figcaption><p>Added Actions for multiuser experiences</p></figcaption></figure>

#### Leave Session

This actions triggers the fact of leaving the current session. It will act for the current player triggering the interaction.

#### End Session

This action will end the multiuser session currently running. You can decide whether *anyone* in the session can end it or only the '*Host*' (first user in the session) can.

#### Mute Microphone

Zoe networking is using Photon Voice framework. This allows to users in a multiuser session to communicate with each other voice. By default the microphone is on and all players can hear each other. You can use this action to mute/unmute the voice input; it acts on the microphone from the local user.

Useful to provide an interface (a toggle button for example) for each user to mute/unmute themselves at will.


# Exporting for Web

To export your experience as a Web app, follow the procedure corresponding to your version of Unity.

{% tabs %}
{% tab title="Unity 6" %}

### Settings for Unity 6

{% embed url="<https://youtu.be/pvr2OW9HqvU>" %}

* From the Unity editor's menu bar, go to Zoe > Build Target Window.

<figure><img src="/files/cYQmTc8FE9jjWqOWFLT1" alt=""><figcaption></figcaption></figure>

* Click on `Switch build target to Web`. Wait a moment for the process to complete.
* Make sure that `Enable Desktop Camera Control` is checked in the inspector of your interactive camera(s) (Interaction Rig).

### What was modified?

When switching the build target to Web, Zoe for Unity automatically modifies several project settings in the background. If you want to double check or are curious, here are the settings that are modified:

{% hint style="info" %}
The steps described below are not needed and should be automatically set up when switching the build profile to Web.
{% endhint %}

* Open File > Build Profiles.
* From the Build Profiles window, click on `Player Settings`.

<figure><img src="/files/JE9Xd4K4HiDHYy6kO4ei" alt=""><figcaption></figcaption></figure>

* Select `Player` from the sidebar.&#x20;
* From the Web tab (symbolized by a world globe), expand `Publishing Settings`.
  * `Compression Format` is set to **Gzip**.
  * `Data Caching` is unchecked.

<figure><img src="/files/BBD7ErQs3tHQFPbmbFZm" alt=""><figcaption></figcaption></figure>

* Select `XR Plug-in Management` from the sidebar, then the Web tab (symbolized by a world globe).
  * `Initialize XR on Startup` is unchecked.

<figure><img src="/files/8kqnfKTJ9LVsCK1bxoo4" alt=""><figcaption></figcaption></figure>
{% endtab %}

{% tab title="Unity 2023 and prior" %}

### Settings for Unity 2023 and prior

{% embed url="<https://youtu.be/LrHKFcdbxKQ?si=ek6-fqAYVTnKo3y7>" %}

* Make sure that `Enable Desktop Camera` is checked in the inspector of your interactive camera(s) (Interaction Rig).
* Go to File > Build Settings.
* Select `WebGL` in the sidebar.
* If you see an `Install with Unity Hub` button, click on it. Unity will then install the necessary WebGL modules. You may need to close and reopen Unity after the process.
* With WebGL selected, click on `Switch Platform` at the bottom of the Build Settings window.&#x20;

{% hint style="info" %}
If you don't see a `Switch Platform` button that means your project is already set up with the correct platform.
{% endhint %}
{% endtab %}
{% endtabs %}

### Exporting for Web

{% hint style="info" %}
This process covers all versions of Unity.
{% endhint %}

* In File > Build Profiles (or Build Settings), make sure all necessary scene(s) of your experience are selected in the Scene List.
* Hit `Build`.
* Name your build, select a folder for it to be exported to, then click `Save`.

It will take a few minutes for your build to export. Once done, your exported files will automatically open in a new window.

### Playing your Experience

Once you've exported a build for web, it's time to play it.

* Select your build and compress it as a .zip file (Windows: right-click on folder, Compress to... > ZIP File / macOS: right-click on folder, Compress "\[Build name]").

{% hint style="info" %}
Make sure to compress the root folder of your build and not a subfolder. The root folder is the one you named when exporting, and it always contains an `index.html` file.
{% endhint %}

* Go to [play.unity.com](https://play.unity.com/en).
* Log into your Unity account, then click on the Upload icon on the right side of the menu bar.
* Select your build's ZIP file or simply drag and drop it into the Upload section.
* Fill in the Title and Description fields, then hit `Save`.

{% hint style="info" %}
If your build's visibility is set to `Public`, you'll be able to share it with anyone via an url address.
{% endhint %}

* Hit the `Play` button to launch your experience!


# Copy of Exporting for Web

To export your experience as a Web app, follow the procedure corresponding to your version of Unity.

{% tabs %}
{% tab title="Unity 6" %}

### Settings for Unity 6

* From the Unity editor's menu bar, go to Zoe > Build Target Window.
* Click on `Switch build target to Web`. Wait a moment for the process to complete.

### Additional Settings

A few settings need to be activated for the Web export to work properly with Unity 6.

* Make sure that `Enable Desktop Camera Control` is checked in the inspector of your interactive camera(s) (Interaction Rig).
* Open File > Build Profiles.
* From the Build Profiles window, click on `Player Settings`.

<figure><img src="/files/JE9Xd4K4HiDHYy6kO4ei" alt=""><figcaption></figcaption></figure>

* Select `Player` from the sidebar.&#x20;
* From the Web tab (symbolized by a world globe), expand `Publishing Settings`.
  * Change `Compression Format` to **Gzip**.
  * Uncheck `Data Caching`.

<figure><img src="/files/BBD7ErQs3tHQFPbmbFZm" alt=""><figcaption></figcaption></figure>

* Select `XR Plug-in Management` from the sidebar.
  * From the Web tab (symbolized by a world globe), uncheck `Initialize XR on Startup`.

<figure><img src="/files/8kqnfKTJ9LVsCK1bxoo4" alt=""><figcaption></figcaption></figure>
{% endtab %}

{% tab title="Unity 2023 and prior" %}

### Settings for Unity 2023 and prior

{% embed url="<https://youtu.be/LrHKFcdbxKQ?si=ek6-fqAYVTnKo3y7>" %}

* Make sure that `Enable Desktop Camera` is checked in the inspector of your interactive camera(s) (Interaction Rig).
* Go to File > Build Settings.
* Select `WebGL` in the sidebar.
* If you see an `Install with Unity Hub` button, click on it. Unity will then install the necessary WebGL modules. You may need to close and reopen Unity after the process.
* With WebGL selected, click on `Switch Platform` at the bottom of the Build Settings window.&#x20;

{% hint style="info" %}
If you don't see a `Switch Platform` button that means your project is already set up with the correct platform.
{% endhint %}
{% endtab %}
{% endtabs %}

### Exporting for Web

{% hint style="info" %}
This process covers all versions of Unity.
{% endhint %}

* In File > Build Profiles (or Build Settings), make sure all necessary scene(s) of your experience are selected in the Scene List.
* Hit `Build`.
* Name your build, select a folder for it to be exported to, then click `Save`.

It will take a few minutes for your build to export. Once done, your exported files will automatically open in a new window.

### Playing your Experience

Once you've exported a build for web, it's time to play it.

* Select your build and compress it as a .zip file (Windows: right-click on folder, Compress to... > ZIP File / macOS: right-click on folder, Compress "\[Build name]").

{% hint style="info" %}
Make sure to compress the root folder of your build and not a subfolder. The root folder is the one you named when exporting, and it always contains an `index.html` file.
{% endhint %}

* Go to [play.unity.com](https://play.unity.com/en).
* Log into your Unity account, then click on the Upload icon on the right side of the menu bar.
* Select your build's ZIP file or simply drag and drop it into the Upload section.
* Fill in the Title and Description fields, then hit `Save`.

{% hint style="info" %}
If your build's visibility is set to `Public`, you'll be able to share it with anyone via an url address.
{% endhint %}

* Hit the `Play` button to launch your experience!


# Exporting for Desktop

To export your experience as a Desktop app (for Windows or macOS), follow the procedure below.

{% embed url="<https://youtu.be/LrHKFcdbxKQ?si=ek6-fqAYVTnKo3y7>" %}
Instructions for Desktop start at 3:11.
{% endembed %}

### Export Settings

* Make sure that `Enable Desktop Camera` is checked in the inspector of your interactive camera(s) (Interaction Rig).
* Go to File > Build Profiles (or Build Settings).
* Select your desired platform in the sidebar: Windows or macOS.

{% hint style="info" %}
In Unity 2023 and prior, you must select `Windows, Mac, Linux` in the sidebar, then your desired platform in `Target Platform`.
{% endhint %}

* If you see an `Install with Unity Hub` button, click on it. Unity will then install the necessary modules for your selected platform. You may need to close and reopen Unity after the process.
* With your platform selected, click on `Switch Platform` at the bottom of the Build Profiles window. If you don't see this button that means your project is already set up with the correct platform.

### Exporting for Desktop

* In File > Build Profiles (or Build Settings), make sure all necessary scene(s) of your experience are selected in the Scene List.
* Hit `Build`.
* Name your build, select a folder for it to be exported to, then click `Save`.

It will take a few minutes for your build to export. Once done, your exported files will automatically open in a new window.

### Playing your Experience

Once you've exported your build, it's time to play!

* Open the .app (for macOS) or .exe (for Windows) file with the name of your experience. That's it!


# Exporting for Meta Quest

{% hint style="danger" %}
This page describes how to export a Meta Quest app using Zoe for Unity prior to version 4.0. The page will soon be updated to support export for Zoe for Unity's newest version.
{% endhint %}

To export your VR experience as an app for Quest headsets, follow this procedure.

{% embed url="<https://youtu.be/pZ0NuQde6vA?si=lJ3uWQNu5q1QeKzK>" %}

* Go to `File > Build Settings`.
* Check that you have **Android** set as your platform. If not, click on `Switch Platform`.

{% hint style="info" %}
If you need to switch to Android mode, Unity will reimport all of your scenes which can take time. It's preferable to do this step early in your project development.
{% endhint %}

* Go to `Player Settings > XR Plug-in Management` and check that you have **'Oculus'** checked in the `Android` tab.

<figure><img src="/files/f5sD9zUkry2VHYuqfSH4" alt=""><figcaption></figcaption></figure>

* Go back to `Build Settings`. Make sure all the scenes you want to include in your app are selected.
* Click the `Build` button, which will generate your app as an .apk file. Pick a spot on your computer for it be exported to.

<div><figure><img src="/files/RYK8fwnOF0qCHO7wxDxW" alt=""><figcaption><p>Select your app's scenes.</p></figcaption></figure> <figure><img src="/files/8sEXPT7w9pggjdRmILkE" alt=""><figcaption><p>Click on 'Build' to create an .apk file.</p></figcaption></figure></div>

Once the .apk file is saved to your computer, follow [this next tutorial](/exporting-your-app/sideloading-on-meta-quest) on how to install it on your headset.


# Sideloading on Meta Quest

### Enabling Developer Mode&#x20;

In order to get access to its file system and install .apk files, your Quest headset needs to be in **Developer Mode**.

To enable it, open the Meta Horizon mobile app and select your headset. Then go to `Headset Settings > Developer Mode` to activate it.

<div><figure><img src="/files/K63xcFJT7QiN02n3KdJw" alt=""><figcaption><p>Headset Settings</p></figcaption></figure> <figure><img src="/files/C3ArLyK8o28WWEX6hesg" alt=""><figcaption><p>Developer Mode</p></figcaption></figure></div>

### Installing and Playing your App

Once you have your finished game or experience (or any intermediate test) exported as an .apk file, it’s time to import it into your VR headset. There are various ways for doing that, but the simplest might be the free software **SideQuest**.

Downloading SideQuest Open the [SideQuest website](https://sidequestvr.com/). Click on `Get SideQuest` and scroll down to find the download link for your operating system—Windows, macOS, or Linux. Make sure you download the **SideQuest Desktop App**, not the SideQuest VR App. Install the app to your computer, then launch it.

If not done already, connect your Quest headset to your computer using a USB cable. A message might pop up in your Quest; confirm it to allow the headset to connect. Look at the upper-left side of SideQuest: your headset’s name should appear there along with a green dot <mark style="color:green;">●</mark> .

{% hint style="info" %}
If your headset appears with an orange dot <mark style="color:orange;">●</mark> , it could mean it's either not in Developer Mode or you need to allow it to connect through a popup message in the Quest.
{% endhint %}

{% hint style="info" %}
If your headset does not show up and you still see a red dot <mark style="color:red;">●</mark> next to a 'Not Detected' message in SideQuest, make sure your Quest is connected to your computer with a USB cable supporting data transfer.
{% endhint %}

### Installing your App Through SideQuest&#x20;

Once your Quest is connected, click on the 'Currently installed apps’ icon in the upper-right corner. The list of apps in your headset should appear.&#x20;

<figure><img src="/files/76RLRKaoqoh8TJiORuim" alt=""><figcaption><p>Select 'Currently installed apps'.</p></figcaption></figure>

You can now simply drag and drop your .apk file in the upper-left section of this window to install it. Wait for the installation process to finish (you can check this at the bottom of the panel or in the `Running tasks` section) before disconnecting our headset from your computer.

<figure><img src="/files/aQtV9E8vxYzxzJAXhvFX" alt=""><figcaption><p>Drag your .apk file into the upper-left corner of the window.</p></figcaption></figure>

### Play your app

Inside your Quest headset, select `Library`. Since your app was installed manually, you won’t see it immediately alongside the other apps. Instead, click on the `Unknown Sources` section. Your app’s name should appear here. Click on it to launch it.


# Introduction: Creator Guidelines

Not every learning experience needs to be built in 3D. When you begin exploring Unity and Zoe for Unity to create your first piece of content, it’s important to choose the right content type for your goals.

These guidelines will help you determine whether your idea is a good fit for 3D, Immersive learning or VR, and how to shape it effectively.

### Spatial Interactivity

Zoe for Unity is fundamentally 3D based and interaction-driven. This means it works best for experiences where learners:

* Explore a space, a story at the first person
* Move around inside an environment
* Pick up, manipulate, or inspect 3D objects
* Investigate systems through hands-on interaction

If these actions are central to your idea, then 3D content built with Unity and Zoe will be a strong choice.

&#x20;

<figure><img src="/files/ltqFHOu0gBDvaXEG1Pbh" alt=""><figcaption><p>Example of a point and click interaction on web</p></figcaption></figure>

Interactive Content Types

{% content-ref url="/pages/F5nT2wJq5nGI7fuPISjC" %}
[Process & Procedure Walkthroughs](/content-guidelines/introduction-creator-guidelines/process-and-procedure-walkthroughs)
{% endcontent-ref %}

{% content-ref url="/pages/ST9hRHqWKy7SAMclHhwU" %}
[Narrative Experiences & Stories](/content-guidelines/introduction-creator-guidelines/narrative-experiences-and-stories)
{% endcontent-ref %}

{% content-ref url="/pages/HMGhoKqDQqOuZ4OrDXzu" %}
[Investigation / Inspection Scenarios](/content-guidelines/introduction-creator-guidelines/investigation-inspection-scenarios)
{% endcontent-ref %}

{% content-ref url="/pages/IfMuwe17eRrkVvlDN6WK" %}
[Puzzles, Challenges & Escape Rooms](/content-guidelines/introduction-creator-guidelines/puzzles-challenges-and-escape-rooms)
{% endcontent-ref %}

{% content-ref url="/pages/DiMtMZ95UwNzDHj1WbIb" %}
[Environmental Simulations](/content-guidelines/introduction-creator-guidelines/environmental-simulations)
{% endcontent-ref %}

{% content-ref url="/pages/pE1VoWtYsaCyXYNTlBcV" %}
[Collaborative / Multi-User Activities](/content-guidelines/introduction-creator-guidelines/collaborative-multi-user-activities)
{% endcontent-ref %}

{% content-ref url="/pages/QroNiqCmFRP0qW4zeeKU" %}
[Mini-Games & Interactive Exercises](/content-guidelines/introduction-creator-guidelines/mini-games-and-interactive-exercises)
{% endcontent-ref %}

{% content-ref url="/pages/22qzGmLP2c6TveH3aFvP" %}
[Full Custom Simulations](/content-guidelines/introduction-creator-guidelines/full-custom-simulations)
{% endcontent-ref %}

***

{% content-ref url="/pages/QgxDyNZ2vDZVqFLYdg8t" %}
[Summary](/content-guidelines/introduction-creator-guidelines/summary)
{% endcontent-ref %}


# Object Exploration

Create 3D scenes where learners explore objects or systems.

Examples:

* Explore a solar system model
* Inspect a biological specimen
* Take apart a mechanical part
* Examine a piece of equipment<br>

Interaction level: low\
\
Interaction type:

* Web: point, rotate, click
* VR: grab, inspect, rotate in your hands<br>

Good for: STEM, engineering, product demos, anatomy, miniature systems understanding.


# Process & Procedure Walkthroughs

Step-by-step lessons where learners follow a set sequence of actions.

Examples:

* Safety checklist for a machine
* Manufacturing task with precise steps
* Lab procedure
* Medical preparation workflow<br>

Format differences:

* Web: move around with mouth, point and click-at objects and hotspots
* VR: hands-on procedural training, pick objects up with hands and physically  move around<br>

Good for: training, onboarding, certification preparation.


# Narrative Experiences & Stories

Scenes that tell a story through space, clues, or choices.

Examples:

* Environmental storytelling (mystery in a forest, lab disaster, historical scene)
* Follow audio logs and notes left behind
* Make decisions that affect the outcome<br>

Format differences:

* Web: choose-your-path scenes, short stories
* VR: immersive role-play, exploration, atmosphere<br>

Good for: humanities, ethics, investigative tasks, environmental science.


# Investigation / Inspection Scenarios

Learners search for clues, identify issues, or analyze evidence.

Examples:

* Identify hazards in a workshop
* Inspect a broken machine
* Search for contamination sources
* Analyze an ecosystem for changes<br>

Format:

* Web: point-and-click inspection, uncover clues by clicking on assets
* VR: hands-on investigation in spatial environments, natural movements<br>

Good for: workplace training, engineering troubleshooting, environmental analysis.


# Puzzles, Challenges & Escape Rooms

Problem-solving content built around goals, constraints, or physical logic.

Examples:

* Assemble components in the right order
* Physics-based puzzles (balance, weight, trajectory)
* Escape room sequences
* Timed challenges with clues<br>

Format:

* Web: logic, sequencing, move from level to level with mouth, Win loose scenarios
* VR: physical interaction + spatial problem solving\ <br>

Good for: STEM learning, gamified lessons, team collaboration.


# Environmental Simulations

Scenes that represent real or future environments and let learners observe, test, or interact.

Examples:

* A forest changing over time
* A factory operating under different conditions
* An ecosystem reacting to pollution
* A future city affected by climate impacts<br>

Format:

* Web: simplified model, move around with mouth and keyboard, click 3D buttons to change before/after scenario
* VR: immersive exploration and interaction by walking around<br>

Good for: climate science, geography, biology, systems thinking.


# Collaborative / Multi-User Activities

Shared scenes where multiple learners work together.

Examples:

* Group lab activity
* Two-person procedure
* Co-op puzzle (both must activate something)
* Instructor-guided class session<br>

Format:

* Web: shared view or simultaneous click interactions ( not available on web yet)
* VR: fully synchronous multiplayer<br>

God for: classrooms, training cohorts, team tasks.

\
Mini-Games & Interactive Exercises

Small, focused, playful activities.

Examples:\ <br>

* Quick reaction challenges\ <br>
* Collect items scattered in the scene\ <br>
* Simple 3D quizzes in a 3D space\ <br>

Format:

* Web: tap/click interactions, move around with mouth.\ <br>
* VR: hand, controller, physics actions\ <br>

Good for: engagement boosters, assessments, fun intros.

## Full Custom Simulations

Complex scenes built for realism, precision, or specialty training.

Examples:

* Operating a CNC machine\ <br>
* Running a full lab setup\ <br>
* Complex medical or industrial workflows\ <br>
* Detailed research simulations for higher ed\ <br>

Format:

* Web: simplified preview version to show the various steps\ <br>
* VR: main training experience with precision\ <br>

Good for: enterprise, advanced courses, certification training.

##

<br>


# Mini-Games & Interactive Exercises

Small, focused, playful activities.

Examples:

* Quick reaction challenges
* Collect items scattered in the scene
* Simple 3D quizzes in a 3D space<br>

Format:

* Web: tap/click interactions, move around with mouth.
* VR: hand, controller, physics actions<br>

Good for: engagement boosters, assessments, fun intros.


# Full Custom Simulations

Complex scenes built for realism, precision, or specialty training.

Examples:

* Operating a CNC machine
* Running a full lab setup
* Complex medical or industrial workflows
* Detailed research simulations for higher ed<br>

Format:

* Web: simplified preview version to show the various steps
* VR: main training experience with precision<br>

Good for: enterprise, advanced courses, certification training.


# Summary

### Content Types vs. Platforms

| Content Type              | Web (Point & Click)                | VR (Immersive) |
| ------------------------- | ---------------------------------- | -------------- |
| Object Exploration        | Limited                            | Yes            |
| Process Walkthroughs      | Yes                                | Yes            |
| Narrative Scenes          | Yes                                | Yes            |
| Investigation Scenarios   | Yes                                | Yes            |
| Puzzles & Challenges      | Yes (logic)                        | Yes (physical) |
| Environmental Simulations | Yes                                | Yes            |
| Multiplayer Activities    | Limited                            | Yes            |
| Mini-Games                | Yes                                | Yes            |
| Full Custom Simulations   | Preview or Simplified Interactions | Yes            |

<br>

<br>


# Getting Started

The following lessons will help you get started with Zoe for Unity .


# Interactive Objects

Interactive Objects (IOs) & Interactions

<table data-view="cards"><thead><tr><th></th><th></th><th></th></tr></thead><tbody><tr><td><strong>Approximate Time</strong></td><td>20 minutes</td><td></td></tr><tr><td><strong>Package Name</strong></td><td>Interactions Lesson Unity Package</td><td></td></tr></tbody></table>

By the end of this lesson, you will know:

* How a Zoe for Unity IO (Interactive Object) is structured;
* How to Transform any asset in an interactive object;
* How to set up an interaction.

### Your Tasks

1. Open Unity.
2. Make sure Zoe for Unity is installed properly.
3. Import the Interactions Lesson Unity Package.
4. Open the Interactions Lesson Scene.
5. Watch all videos of the following playlist. These will guide you through the basics of setting up this lesson's interactions.

{% embed url="<https://www.youtube.com/playlist?list=PLEQTZWgCVZdfpggaaj5lYEjw_1y5H8GOW>" %}
"Zoe for Unity: Topic 3 - Interactive Objects" playlist (click at the upper-right corner icon for the full list)
{% endembed %}

### Additional Resources

{% content-ref url="/pages/BWfzWX5dFpaq2tecl9a1" %}
[Translate](/adding-interactivity/interactions/actions/translate)
{% endcontent-ref %}

{% content-ref url="/pages/9qk0zIk6fLswsX0YYP2K" %}
[Rotate](/adding-interactivity/interactions/actions/rotate)
{% endcontent-ref %}

{% content-ref url="/pages/bmcPJNticQ6ZLZNdsW3w" %}
[Audio](/adding-interactivity/interactions/actions/audio)
{% endcontent-ref %}


# Actions 01

Translate | Rotate | Play Audio | Controller Vibrate

<table data-view="cards"><thead><tr><th></th><th></th><th></th></tr></thead><tbody><tr><td><strong>Approximate Time</strong></td><td>20 minutes</td><td></td></tr><tr><td><strong>Package Name</strong></td><td>Interactions Lesson Unity Package</td><td></td></tr></tbody></table>

By the end of this lesson, you will know:

* How to make an object move (Translate) in an interaction;
* How to make an object rotate in an interaction;
* Know how to play or mute audio in an interaction.

### Your Tasks

1. Open Unity.
2. Make sure Zoe for Unity is installed properly.
3. Import the Interactions Lesson Unity Package.
4. Open the Interactions Lesson Scene
5. Watch all videos of the following playlist. These will guide you through the basics of setting up this lesson's interactions.

{% embed url="<https://youtube.com/playlist?list=PLEQTZWgCVZde-sSUVDHDXzKNB7feJTgDM&si=AT-QFhtBJP33Abx5>" %}
"Zoe for Unity: Interactions - Actions 01" playlist (click at the upper-right corner icon for the full list)
{% endembed %}

### Additional Resources

{% content-ref url="/pages/BWfzWX5dFpaq2tecl9a1" %}
[Translate](/adding-interactivity/interactions/actions/translate)
{% endcontent-ref %}

{% content-ref url="/pages/9qk0zIk6fLswsX0YYP2K" %}
[Rotate](/adding-interactivity/interactions/actions/rotate)
{% endcontent-ref %}

{% content-ref url="/pages/bmcPJNticQ6ZLZNdsW3w" %}
[Audio](/adding-interactivity/interactions/actions/audio)
{% endcontent-ref %}


# Actions 02

Physics | Change Manipulation | Change Material | Fade Transition

<table data-view="cards"><thead><tr><th></th><th></th><th></th></tr></thead><tbody><tr><td><strong>Approximate Time</strong></td><td>20 minutes</td><td></td></tr><tr><td><strong>Package Name</strong></td><td>Interactions Lesson Unity Package</td><td></td></tr></tbody></table>

By the end of this lesson, you will know:

* How to make the physical properties of an IO change in an interaction;
* How to make the manipulation mode of an IO change in an interaction;
* How to make the material of an IO change in an interaction;
* How to use the Fade transition to switch scenes in your experience.

### Your Tasks

1. Open Unity.
2. Make sure Zoe for Unity is installed properly.
3. Import the Interactions Lesson Unity Package.
4. Open the Interactions Lesson Scene.
5. Watch all videos of the following playlist. These will guide you through the basics of setting up this lesson's interactions.

{% embed url="<https://youtube.com/playlist?list=PLEQTZWgCVZdc9CaaYY3VEOMHUQkZCe74M&si=EQkKsbOd09q0RQdD>" %}
"Zoe for Unity: Interactions - Actions 02" playlist (click at the upper-right corner icon for the full list)
{% endembed %}

### Additional Resources

{% content-ref url="/pages/BtvlK2XZ9A7RuzOoAl1g" %}
[Physics](/adding-interactivity/interactions/actions/physics)
{% endcontent-ref %}

{% content-ref url="/pages/tLMVH0kp0Xf24BSPloEO" %}
[Change Material](/adding-interactivity/interactions/actions/change-material)
{% endcontent-ref %}


# Conditions 01

Available soon!


# Conditions 02

Available soon!


# Start Here

Use this section to understand Bridge XR before setup or content creation.

Read these pages in order:

1. [Overview](/bridge-xr/start-here/overview)
2. [Getting Started](/bridge-xr/start-here/getting-started)
3. [Roles & Permissions](/bridge-xr/start-here/roles-and-permissions)
4. [Architecture & Requirements](/bridge-xr/start-here/architecture-and-requirements)

### Use this section if you are

* new to Bridge XR
* defining roles
* planning rollout
* preparing a Unity workflow

### What you will learn

* what Bridge XR includes
* how teams usually roll it out
* who owns each part
* what needs to be installed and configured


# Overview

What is BridgeXR?

Bridge XR is a self-hosted platform for creating, delivering, and tracking immersive learning experiences.

It connects your institution's infrastructure, Unity workflow, and playback on Meta Quest and the web.

### Bridge XR has 3 main parts

#### 1. Web Dashboard

Use the web dashboard to manage the platform.

* manage members and roles
* create and publish modules
* share module CODEs
* review analytics
* launch supported web experiences through the web player

#### 2. Bridge XR App

Use the app to join modules and play headset experiences.

* supports Meta Quest headsets
* provides headset-based playback
* supports guest access
* sends activity data back to the dashboard

#### 3. Unity authoring workflow

Developers create experiences in Unity with:

* **Zoe for Unity**
* the **Bridge XR integration package**

Together, they let developers:

* build experiences
* add Bridge-specific tracking
* mark experience completion
* export web builds for browser-based playback
* upload bundles to the Bridge XR platform

### Playback options

Bridge XR has two main playback surfaces:

* the **Bridge XR App** for installed Meta Quest playback
* the **web player** for Unity experiences exported for the web

The playback path depends on how the developer exports the experience.

{% hint style="info" %}
In many educational institutions, the developer role may be handled by students, faculty teams, or external partners.
{% endhint %}

### How the platform works

1. IT deploys Bridge XR on the institution's infrastructure.
2. Administrators add members and assign roles.
3. Developers build and upload experiences from Unity.
4. Coaches create modules from those experiences.
5. Participants join modules with a CODE and play.
6. Analytics flow back to the dashboard.

### Who usually uses what

* **IT and platform owners**: deployment, SSO, app distribution
* **Administrators**: members, roles, billing, oversight
* **Developers**: Unity, Zoe for Unity, Bridge XR integration package
* **Coaches and facilitators**: modules, participant management, analytics
* **Participants**: Meta Quest app or web player

<figure><img src="/files/btFKWbmGaW38pYh3oMAv" alt="Bridge XR platform overview"><figcaption><p>Bridge XR platform overview</p></figcaption></figure>


# Previous version

Archived previous version for internal reference.

### General Overview

The Bridge XR platform lets you effortlessly create interactive 3D experiences for XR devices, web, desktop and distribute them on your own dashboard, and access powerful analytics to track engagement and performance.

There are three elements that make the Bridge Suite:

1. The Bridge XR web dashboard to manage and play content (hosted on your servers);
2. The Bridge XR App (which will be shared with you);
3. The Zoe for Unity plugin to create your content.

<figure><img src="/files/W2qtdOfhY6hVyhL0ZFc7" alt="" width="188"><figcaption></figcaption></figure>

<figure><img src="/files/btFKWbmGaW38pYh3oMAv" alt=""><figcaption></figcaption></figure>

### XR App

The Bridge XR App is where participants join modules, load and play experiences.

<figure><img src="/files/XZTq3LPOuduSeOd1BniU" alt=""><figcaption></figcaption></figure>

Key Elements:

* Supported platforms: XR or Desktop
* Allows guest participants
* Sends statistics to dashboard

### Web Dashboard

<figure><img src="/files/0cgquCtxUvFKNSyNCWdr" alt=""><figcaption></figcaption></figure>

The Web dashboard is primarily for Admins and Coaches. It provides members, modules and games management.

It can also be accessed by Participants to join modules and play experiences on the Web.

Key Elements:

* Platform: Web Browser
* For Admins and Coaches to manage members and modules
* For Participants to play experiences
* Contains modules statistics
* Requires authentication to access management

### Zoe for Unity

Create your own immersive experiences easily thanks to Zoe for Unity. Then export your application directly to your Bridge XR dashboard.

<figure><img src="/files/hhebaPkjBeetcpYMDbnC" alt=""><figcaption></figcaption></figure>

Key Elements:

* Requires Unity3D engine plugin
* Directly push bundles to server with a Wizard interface
* Requires Developer authentication


# Getting Started

Start here based on your role in Bridge XR.

Use this page to find the right starting point fast.

Most teams follow this order:

1. IT deploys the platform.
2. Admins add members and assign roles.
3. Developers build and upload experiences.
4. Coaches create modules and share the CODE.
5. Participants join and play.

In many education deployments, developers are internal teams, external partners, or students building experiences as part of a course or project.

{% hint style="info" %}
If you are not sure where to start, read [Overview](/bridge-xr/start-here/overview) first, then check [Roles & Permissions](/bridge-xr/start-here/roles-and-permissions).
{% endhint %}

### Before you begin

* Bridge XR is self-hosted on your own cloud infrastructure.
* Organization members sign in with institution SSO or credentials set by IT.
* Guests can join a module with a CODE and their full name.
* Guest activity is device-based. A new device creates a new entry.
* Experiences can run in the browser through the **web player** or on **Meta Quest** through the installed **Bridge XR App**.

### Quick start by role

{% stepper %}
{% step %}

### IT or platform owner

Set up the platform first.

* Deploy the backend and web dashboard with [Server Deployment](/bridge-xr/set-up-bridge-xr/server-deployment).
* Configure identity with [SSO configuration](/bridge-xr/set-up-bridge-xr/server-deployment/sso-configuration) and [SSO Integration](/bridge-xr/set-up-bridge-xr/server-deployment/sso-integration).
* Distribute the headset app with [Install and Distribute the Bridge XR App](/bridge-xr/set-up-bridge-xr/install-and-distribute-the-bridge-xr-app).
  {% endstep %}

{% step %}

### Administrator

Prepare the organization and access.

* Review access levels in [Roles & Permissions](/bridge-xr/start-here/roles-and-permissions).
* Add members and manage roles in [Manage Organization and Members](/bridge-xr/use-bridge-xr/manage-organization-and-members).
* Confirm developers and coaches have the right access before rollout.
  {% endstep %}

{% step %}

### Developer

Build, prepare, and publish experiences.

{% hint style="info" %}
In many educational institutions, this role is often handled by students building experiences as part of a course, studio, or project.
{% endhint %}

* Build in Unity with **Zoe for Unity**.
* Add the **Bridge XR integration package** to connect the experience to Bridge XR.
* Add Bridge XR tracking and completion actions.
* Upload builds with [Upload Experiences from Unity](/bridge-xr/build-with-unity/upload-experiences-from-unity).
* Test the published version with [Test Published Experiences](/bridge-xr/build-with-unity/test-published-experiences).
  {% endstep %}

{% step %}

### Coach or facilitator

Turn published experiences into a playable module.

* Create a module in [Create and Manage Modules](/bridge-xr/use-bridge-xr/create-and-manage-modules).
* Add one or more experiences.
* Publish the module and share the CODE with participants.
* Use the same module page to track participants and analytics.
  {% endstep %}

{% step %}

### Participant

Join the module and start playing.

* Open the web dashboard for browser playback or the Bridge XR App for Meta Quest playback.
* Enter the CODE shared by your coach.
* Follow [Join Modules and Play](/bridge-xr/use-bridge-xr/join-modules-and-play).
  {% endstep %}
  {% endstepper %}

### Bridge XR terms

* **Experience**: a Unity experience built with Zoe for Unity and connected to Bridge XR.
* **Module**: a shareable collection of experiences for one learning session.
* **Bundle**: the packaged build a developer uploads to the server.

### Which part of Bridge XR do I use?

* **Web Dashboard**: manage members, modules, and analytics. It also includes the **web player** for supported Unity web exports.
* **Bridge XR App**: the installed player for Meta Quest headset experiences.
* **Zoe for Unity + Bridge XR package**: create experiences in Unity, add Bridge XR integration, and publish them to Bridge XR.

### User flow diagram

Use this diagram as a visual overview of the platform flow across roles.

<figure><img src="/files/oAWxl08ATEAgnGQCx0sd" alt="Bridge XR user flow diagram"><figcaption><p>Bridge XR user flow diagram</p></figcaption></figure>


# Previous version

Archived previous version for internal reference.

### Good to Know

* All organization users need to authenticate either with their existing institution SSO or with an email+password provided by the IT department for the main Administrator.
* External end users can also join modules as guests but data entry is created every time they join from a different device.
* A CODE is required to join a module.
* The platform is self-hosted on your own cloud infrastructure.

### Dictionary

<table><thead><tr><th width="149.58203125">WORD</th><th>DESCRIPTION</th></tr></thead><tbody><tr><td>Experience</td><td>Story, game, or simulation built with Zoe for Unity to be played by participants.</td></tr><tr><td>Module</td><td>Created by educators/coaches, composed of one or several experiences, shared via CODE to participants to join.</td></tr><tr><td>Bundle</td><td>This term is used by developers exporting experiences to the server as ‘bundles’.</td></tr></tbody></table>

### Users Flows

<figure><img src="/files/oAWxl08ATEAgnGQCx0sd" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
For IT members in order to deploy BridgeXR on your servers, follow [Server Deployment](/bridge-xr/set-up-bridge-xr/server-deployment).

For IT members in order to get access to the BridgeXR App, follow [Install and Distribute the Bridge XR App](/bridge-xr/set-up-bridge-xr/install-and-distribute-the-bridge-xr-app).

For Developers to create and upload experiences, follow [Develop Experiences in Unity](/bridge-xr/build-with-unity/develop-experiences-in-unity).

For Coaches to create modules and distribute them, follow [Create and Manage Modules](/bridge-xr/use-bridge-xr/create-and-manage-modules).

For Participants to join modules and play experiences, follow [Join Modules and Play](/bridge-xr/use-bridge-xr/join-modules-and-play).

For Administrators to manage organization members, follow [Manage Organization and Members](/bridge-xr/use-bridge-xr/manage-organization-and-members).
{% endhint %}


# Roles & Permissions

Use this page to understand who does what in Bridge XR.

### Roles at a glance

#### Administrator

Administrators manage the institution's Bridge XR workspace.

They handle members, roles, billing, and overall oversight.

#### Developer

Developers build experiences in Unity with **Zoe for Unity** and the **Bridge XR integration package**.

They create and update experiences, upload bundles, playtest content, and review analytics for the modules they create.

{% hint style="info" %}
In many educational institutions, developers may be students, faculty teams, or external partners.
{% endhint %}

#### Coach or facilitator

Coaches run the learning experience.

They create modules, add experiences, share CODEs, facilitate sessions, and review module analytics.

#### Participant

Participants are the end users of the experience.

They join modules with a CODE and play the experiences available to them.

### Permissions

* **Only administrators** manage members, roles, and billing.
* **Developers and administrators** create and update experiences.
* **Administrators, developers, and coaches** can create modules.
* **Coaches and participants** can join modules.
* **Participants** cannot manage the organization or view analytics.

<table><thead><tr><th width="239.6015625">Permission</th><th align="center">Admins</th><th align="center">Developers</th><th align="center">Coaches/ Facilitators</th><th align="center">Participants</th></tr></thead><tbody><tr><td>Can add other members</td><td align="center"><mark style="color:$success;">√</mark></td><td align="center"><mark style="color:red;">X</mark></td><td align="center"><mark style="color:red;">X</mark></td><td align="center"><mark style="color:red;">X</mark></td></tr><tr><td>Can manage member roles</td><td align="center"><mark style="color:$success;">√</mark></td><td align="center"><mark style="color:red;">X</mark></td><td align="center"><mark style="color:red;">X</mark></td><td align="center"><mark style="color:red;">X</mark></td></tr><tr><td>Can delete members</td><td align="center"><mark style="color:$success;">√</mark></td><td align="center"><mark style="color:red;">X</mark></td><td align="center"><mark style="color:red;">X</mark></td><td align="center"><mark style="color:red;">X</mark></td></tr><tr><td>Can see billing</td><td align="center"><mark style="color:$success;">√</mark></td><td align="center"><mark style="color:red;">X</mark></td><td align="center"><mark style="color:red;">X</mark></td><td align="center"><mark style="color:red;">X</mark></td></tr><tr><td>Can create experiences</td><td align="center"><mark style="color:$success;">√</mark></td><td align="center"><mark style="color:$success;">√</mark></td><td align="center"><mark style="color:red;">X</mark></td><td align="center"><mark style="color:red;">X</mark></td></tr><tr><td>Can update experiences</td><td align="center"><mark style="color:$success;">√</mark></td><td align="center"><mark style="color:$success;">√</mark></td><td align="center"><mark style="color:red;">X</mark></td><td align="center"><mark style="color:red;">X</mark></td></tr><tr><td>Can play experiences</td><td align="center">They can playtest</td><td align="center">They can playtest</td><td align="center">They can playtest</td><td align="center"><mark style="color:$success;">√</mark></td></tr><tr><td>Can create modules</td><td align="center"><mark style="color:$success;">√</mark></td><td align="center"><mark style="color:$success;">√</mark></td><td align="center"><mark style="color:$success;">√</mark></td><td align="center"><mark style="color:red;">X</mark></td></tr><tr><td>Can see all modules</td><td align="center"><mark style="color:$success;">√</mark></td><td align="center">Only the ones they create</td><td align="center">Only the ones they create</td><td align="center">Only the ones they have the CODE to</td></tr><tr><td>Can see analytics</td><td align="center"><mark style="color:$success;">√</mark></td><td align="center"><mark style="color:$success;">√</mark></td><td align="center"><mark style="color:$success;">√</mark></td><td align="center"><mark style="color:red;">X</mark></td></tr><tr><td>Can join modules</td><td align="center"><mark style="color:red;">X</mark></td><td align="center"><mark style="color:red;">X</mark></td><td align="center"><mark style="color:$success;">√</mark></td><td align="center">The ones they have a CODE to</td></tr></tbody></table>

### Choose your path

* If you are setting up the platform, go to [Set Up Bridge XR](/bridge-xr/set-up-bridge-xr).
* If you are building content in Unity, go to [Build with Unity](/bridge-xr/build-with-unity).
* If you are managing modules or participants, go to [Use Bridge XR](/bridge-xr/use-bridge-xr).


# Previous version

Archived previous version for internal reference.

### Platform Roles

<table><thead><tr><th width="149.58203125">WORD</th><th>DESCRIPTION</th></tr></thead><tbody><tr><td>Administrators</td><td>Have access to billing and can add/remove any member of the organization.</td></tr><tr><td>Coaches</td><td>Learning leaders, they create modules and invite participants.</td></tr><tr><td>Participants</td><td>End users of the platform, they join modules and play experiences.</td></tr><tr><td>Developers</td><td>They develop learning experiences with Zoe for Unity and upload them to the Dashboard.</td></tr></tbody></table>

### Permissions

<table><thead><tr><th width="239.6015625">Permission</th><th align="center">Admins</th><th align="center">Developers</th><th align="center">Coaches/ Facilitators</th><th align="center">Participants</th></tr></thead><tbody><tr><td>Can add other members</td><td align="center"><mark style="color:$success;">√</mark></td><td align="center"><mark style="color:red;">X</mark></td><td align="center"><mark style="color:red;">X</mark></td><td align="center"><mark style="color:red;">X</mark></td></tr><tr><td>Can change a member’s role</td><td align="center"><mark style="color:$success;">√</mark></td><td align="center"><mark style="color:red;">X</mark></td><td align="center"><mark style="color:red;">X</mark></td><td align="center"><mark style="color:red;">X</mark></td></tr><tr><td>Can delete members</td><td align="center"><mark style="color:$success;">√</mark></td><td align="center"><mark style="color:red;">X</mark></td><td align="center"><mark style="color:red;">X</mark></td><td align="center"><mark style="color:red;">X</mark></td></tr><tr><td>Can see billing</td><td align="center"><mark style="color:$success;">√</mark></td><td align="center"><mark style="color:red;">X</mark></td><td align="center"><mark style="color:red;">X</mark></td><td align="center"><mark style="color:red;">X</mark></td></tr><tr><td>Can create experiences</td><td align="center"><mark style="color:$success;">√</mark></td><td align="center"><mark style="color:$success;">√</mark></td><td align="center"><mark style="color:red;">X</mark></td><td align="center"><mark style="color:red;">X</mark></td></tr><tr><td>Can update experiences</td><td align="center"><mark style="color:$success;">√</mark></td><td align="center"><mark style="color:$success;">√</mark></td><td align="center"><mark style="color:red;">X</mark></td><td align="center"><mark style="color:red;">X</mark></td></tr><tr><td>Can play experiences</td><td align="center">They can playtest</td><td align="center">They can playtest</td><td align="center">They can playtest</td><td align="center"><mark style="color:$success;">√</mark></td></tr><tr><td>Can create modules</td><td align="center"><mark style="color:$success;">√</mark></td><td align="center"><mark style="color:$success;">√</mark></td><td align="center"><mark style="color:$success;">√</mark></td><td align="center"><mark style="color:red;">X</mark></td></tr><tr><td>Can see all modules</td><td align="center"><mark style="color:$success;">√</mark></td><td align="center">Only the ones they create</td><td align="center">Only the ones they create</td><td align="center">Only the ones they have the CODE to</td></tr><tr><td>Can see analytics</td><td align="center"><mark style="color:$success;">√</mark></td><td align="center"><mark style="color:$success;">√</mark></td><td align="center"><mark style="color:$success;">√</mark></td><td align="center"><mark style="color:red;">X</mark></td></tr><tr><td>Can join modules</td><td align="center"><mark style="color:red;">X</mark></td><td align="center"><mark style="color:red;">X</mark></td><td align="center"><mark style="color:$success;">√</mark></td><td align="center">The ones they have a CODE to</td></tr></tbody></table>


# Architecture & Requirements

Core Bridge XR components and infrastructure requirements.

Bridge XR combines hosted services, playback surfaces, and a Unity workflow.

### Core components

#### Authentication

Bridge XR can connect to your institution's existing SSO provider.

#### Backend services

The backend runs in your cloud environment and handles platform logic, data, and experience delivery.

#### Storage and database

You need:

* object storage for uploaded experience bundles
* a PostgreSQL database for platform data

#### Web Dashboard

The web dashboard is the browser-based management surface.

It is hosted on your infrastructure and includes the **web player** for Unity web exports.

#### Bridge XR App

The app is the installed client used to play experiences on Meta Quest headsets.

This is the headset-based player in the Bridge XR platform.

#### Unity authoring stack

Developers need:

* Unity
* **Zoe for Unity**
* the **Bridge XR integration package**

This stack is used to build, prepare, and upload experiences.

Developers can export for different playback targets, including the web.

### What your team needs to plan

* a URL for the web dashboard
* a cloud environment for frontend and backend hosting
* object storage
* a PostgreSQL database
* an SSO setup
* a distribution method for the Bridge XR app
* a plan for which experiences run in the browser and which run on Meta Quest

### Typical ownership

* **IT / platform owners**: infrastructure, SSO, app rollout
* **Administrators**: workspace setup and member access
* **Developers**: Unity workflow and uploads

### Infrastructure diagram

<figure><img src="/files/yb4FyUdcWLzicPeqOaFZ" alt="Bridge XR infrastructure diagram"><figcaption><p>Bridge XR infrastructure diagram</p></figcaption></figure>


# Previous version

Archived previous version for internal reference.

<table><thead><tr><th width="149.58203125">COMPONENT</th><th>SUPPORTED/REQUIRED PLATFORMS</th></tr></thead><tbody><tr><td>Authentication</td><td>Your existing SSO (Microsoft for ex.) can be integrated.</td></tr><tr><td>Backend</td><td>Cloud Service such as Amazon, Azure, Google Cloud or other.</td></tr><tr><td>Frontend</td><td>XR app on VR headsets or Desktop, and Web frontend.</td></tr><tr><td>Zoe for Unity</td><td>Unity 3D Engine is required to develop with Zoe.</td></tr></tbody></table>

### Infrastructure

<figure><img src="/files/yb4FyUdcWLzicPeqOaFZ" alt=""><figcaption></figcaption></figure>


# Previous version

Archived previous version for internal reference.

Use this section to understand how Bridge XR fits together.

Start here if you are new to the platform.

* Read **Overview** for the product model.
* Read **Getting Started** for the main rollout path.
* Read **Roles & Permissions** to identify each audience.
* Read **Architecture & Requirements** to understand the core components.


# Set Up Bridge XR

Use this section to deploy Bridge XR and prepare access.

This section is mainly for IT teams and platform owners.

### Recommended order

1. Deploy the Bridge XR backend and web dashboard.
2. Configure your identity provider.
3. Connect SSO to the deployed frontend.
4. Distribute the installed XR app to Meta Quest headsets if needed.

### What this section covers

* infrastructure and hosting
* dashboard URL
* SSO configuration
* SSO integration
* XR app distribution for Meta Quest

{% hint style="info" %}
The web player runs in the browser through the web dashboard. It does not require installing the XR app.
{% endhint %}

### Pages in this section

* [Server Deployment](/bridge-xr/set-up-bridge-xr/server-deployment)
* [SSO configuration](/bridge-xr/set-up-bridge-xr/server-deployment/sso-configuration)
* [SSO Integration](/bridge-xr/set-up-bridge-xr/server-deployment/sso-integration)
* [Install and Distribute the Bridge XR App](/bridge-xr/set-up-bridge-xr/install-and-distribute-the-bridge-xr-app)


# Server Deployment

Guidelines to deploy BridgeXR backend and web frontend on your servers.

Use this page to deploy the Bridge XR backend and web dashboard on your own infrastructure.

### What gets deployed

Your deployment includes:

* the **backend**
* the **web dashboard**
* the **web player** for browser-based experiences
* storage and database services used by the platform

{% hint style="info" %}
The Bridge XR App is separate from this deployment flow. It is distributed to **Meta Quest headsets** after the platform is live.
{% endhint %}

### Before you start

1. Fill out the [onboarding form](https://bridge-xr-form.lovable.app/).
2. Define the dashboard URL, such as `bridgexr.yourdomain.com`.
3. Share that URL with the Zoe Immersive team as early as possible.
4. Prepare your SSO setup with [SSO configuration](/bridge-xr/set-up-bridge-xr/server-deployment/sso-configuration).

{% hint style="warning" %}
Without the final dashboard URL, your Bridge XR client apps cannot point to the correct server.
{% endhint %}

### Infrastructure requirements

You need:

* S3-compatible object storage or Azure Blob Storage
* a PostgreSQL database
* a Bridge XR backend service
* a Bridge XR frontend service

#### Suggested starting sizes

* backend: around `10 GB` storage, `2 CPU`, `2 GB RAM`
* object storage: around `50 GB` to start
* database: around `20 GB` to start

Actual sizing depends on experience size, participant count, and usage frequency.

### Deployment steps

{% hint style="info" %}
For detailed information on the following steps please check the [Technical Guide](/bridge-xr/set-up-bridge-xr/server-deployment/technical-guide).
{% endhint %}

1. Download the Bridge XR **Web Files** from the Zoe for Unity [download page](https://zoeimmersive.com/unity/download/). Note: Make sure you are logged in with the correct account; otherwise you won't see those files.
2. Deploy the frontend files to a web server suitable for a single-page app.
3. Run the backend service on your Linux environment.
4. Seed the database with the provided script.
5. Connect SSO with [SSO Integration](/bridge-xr/set-up-bridge-xr/server-deployment/sso-integration).
6. Validate the platform in a testing environment if available.
7. Promote the deployment to production.

### After deployment

Once deployment is complete:

* add members in [Manage Organization and Members](/bridge-xr/use-bridge-xr/manage-organization-and-members)
* create modules in [Create and Manage Modules](/bridge-xr/use-bridge-xr/create-and-manage-modules)
* distribute the XR app to Meta Quest headsets.


# Technical Guide

Detailed guide on how to deploy the cloud backend and frontend files on your servers.

### 1. BridgeXR

The BridgeXR management application consists of a simple frontend and backend. We provide everything needed to deploy both applications and an example configuration in the deployment package. Keep in mind that the provided configuration is an example and needs to be adjusted to be deployed for production use if you choose to do so. The provided configuration example showcases all mandatory settings needed to run the application.

### 2. Azure Integration

We provide integration with Azure Active Directory B2C SSO (3. SSO Integration), Azure Key Vault (5.2 Configuration) and Azure Blob Storage (5.1.2 Object Storage).

### 3. SSO Integration

#### 3.1 Azure Active Directory B2C

In order to integrate with Azure Active Directory B2C SSO we need the following parameters:

**Frontend:**

* Application (client) ID
* Authority URL

**Backend:**

* JWKS URI (found in the openid-configuration of the Azure AD B2C tenant)

For the frontend, the `Application (client) ID` and `Authority URL` are needed to configure the MSAL library used for authentication and have to be set in the `msal.json` found in the `public` directory of the supplied frontend files.

For the backend, the `JWKS URI` is needed to validate the tokens issued by Azure AD B2C and has to be set in the `OidcKeysURL` configuration key.

The `API permissions` needed are as follows:

* `User.Read`
* `email`
* `profile`

The redirect URIs under `Authentication` need to be configured as follows:

* Single-page application
  * `https://<host>/msal-login-popup` — needed for the Web Dashboard
  * `http://localhost:51273/StreamingAssets/callback.html` — needed for the Unity Wizard
* Android
  * `msauth://com.zoe.bridgexr.client/<hash>` — needed for the Android client (for more information about the hash consult the app documentation or contact us)
* Mobile and desktop applications
  * `unityhub://editor/authentication.editorAddons.editorLink/oauth2/`
  * `http://localhost:8080/zoe/bridgexr/oauth2/`

Refer to [msal-client-application-configuration](https://learn.microsoft.com/en-us/entra/identity-platform/msal-client-application-configuration) for more information.

#### 3.2 Others

If a different SSO integration is needed, please contact us.

If no SSO integration is provided, the only way to log in is with credentials manually managed in the database. BridgeXR does not provide management facilities for user credentials.

### 4. Frontend

The frontend application is delivered as a folder of static files that must be served as a Single Page Application (SPA) on your own infrastructure.

The routing is handled client-side, so the web server should always return the `index.html` file for any unknown paths, rather than a 404.

The frontend requires `/api` to be mapped to the backend while stripping the `/api` prefix (e.g., `https://frontend.local/api/foo/bar` gets redirected to `http[s]://backend.local/foo/bar` internally).

The frontend files must be served over HTTPS, and the following headers must be set to allow the WebGPU component to work:

* `Cross-Origin-Opener-Policy: same-origin`
* `Cross-Origin-Embedder-Policy: require-corp`

Refer to [SharedArrayBuffer#security\_requirements](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer#security_requirements) for more information.

For files served from `/WebGL/` the appropriate gzip headers must be set for the browser to transparently use the compressed files.

We provide an example nginx configuration for serving the frontend and proxying to the backend. If you use a different web server and encounter deployment issues, please contact us.

### 5. Backend

The backend consists of a standalone binary for `x86-64-linux` that can be deployed via most contemporary mechanisms. If a different target is needed, please contact us.

Configuration is handled via environment variables, configuration files, or integrations with configuration providers, as outlined in §5.2 Configuration.

There are no additional requirements regarding the deployment method, so deploying on a Virtual Machine or Container from any provider should be possible.

We provide a prefilled (as far as possible) example config file and Dockerfile for the backend. If you encounter issues running the provided binary on your chosen infrastructure, please contact us.

#### 5.1 Dependencies on External Services

**Postgres**

The backend uses a Postgres database to store most of its data.

Database migrations are handled by the backend, which assumes full access to the database defined in the application's connection string.

We do not provide backups on our side, so setting up a backup strategy for the database is the responsibility of the deployer.

**Object Storage**

For binary data, we defer to mature object storage solutions, and provide integrations with Azure Blob Storage and S3-compatible object storage.

We do not provide backups on our side, so setting up a backup strategy for the object storage is the responsibility of the deployer.

**Azure Blob Storage**

We provide integration with Azure Blob Storage for storing data. If you encounter issues with our Azure Blob Storage integration, please contact us.

**S3-compatible Object Storage**

We provide integration with S3-compatible object storage solutions for storing data.

This is tested using MinIO and AWS S3. If you encounter issues with a different S3-compatible storage solution, please contact us.

#### 5.2 Configuration

The backend can be configured via:

* Configuration files (`config.{json,yaml}`, `.env`)
* Command-line flags
* Environment variables
* Azure Key Vault

The specific keys which can be configured are found in the Appendix.

***

### Appendix: Configuration Keys

| Name                       | Description                                                                | CLI                                                                   | JSON/YAML                                                                  | Env/Dotenv                                                              | Azure Key Vault                                                                            |
| -------------------------- | -------------------------------------------------------------------------- | --------------------------------------------------------------------- | -------------------------------------------------------------------------- | ----------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
| Host                       | Host the main api server binds to                                          | `--host 0.0.0.0`                                                      | `{"HOST": "0.0.0.0"}`                                                      | `RCL_HOST=0.0.0.0`                                                      | `Name: host \| Secret Value: 0.0.0.0`                                                      |
| Port                       | Port the main api server binds to                                          | `--port 8080`                                                         | `{"PORT": "8080"}`                                                         | `RCL_PORT=8080`                                                         | `Name: port \| Secret Value: 8080`                                                         |
| Log Level                  | Log level for the server                                                   | `--log-level INFO`                                                    | `{"LOG_LEVEL": "INFO"}`                                                    | `RCL_LOG_LEVEL=INFO`                                                    | `Name: log-level \| Secret Value: INFO`                                                    |
| Jwt Duration               | Duration of JWT tokens created by the application                          | `--jwt-duration 1h`                                                   | `{"JWT_DURATION": "1h"}`                                                   | `RCL_JWT_DURATION=1h`                                                   | `Name: jwt-duration \| Secret Value: 1h`                                                   |
| Refresh Duration           | Duration of refresh tokens created by the application                      | `--refresh-duration 0`                                                | `{"REFRESH_DURATION": "0"}`                                                | `RCL_REFRESH_DURATION=0`                                                | `Name: refresh-duration \| Secret Value: 0`                                                |
| Jwt Private Key Path       | Path to JWT private key                                                    | `--jwt-private-key-path /opt/jwt.pem`                                 | `{"JWT_PRIVATE_KEY_PATH": "/opt/jwt.pem"}`                                 | `RCL_JWT_PRIVATE_KEY_PATH=/opt/jwt.pem`                                 | `Name: jwt-private-key-path \| Secret Value: /opt/jwt.pem`                                 |
| Db Connection String       | Connection string to the postgres database                                 | `--db-connection-string postgres://user:pass@localhost:5432/BridgeXR` | `{"DB_CONNECTION_STRING": "postgres://user:pass@localhost:5432/BridgeXR"}` | `RCL_DB_CONNECTION_STRING=postgres://user:pass@localhost:5432/BridgeXR` | `Name: db-connection-string \| Secret Value: postgres://user:pass@localhost:5432/BridgeXR` |
| Aws Endpoint               | AWS endpoint parameter for S3-compatible object storage                    | `--aws-endpoint minio.example.com:9900`                               | `{"AWS_ENDPOINT": "minio.example.com:9900"}`                               | `RCL_AWS_ENDPOINT=minio.example.com:9900`                               | `Name: aws-endpoint \| Secret Value: minio.example.com:9900`                               |
| Aws Access Key ID          | AWS access key id parameter for S3-compatible object storage               | `--aws-access-key-id minio_user`                                      | `{"AWS_ACCESS_KEY_ID": "minio_user"}`                                      | `RCL_AWS_ACCESS_KEY_ID=minio_user`                                      | `Name: aws-access-key-id \| Secret Value: minio_user`                                      |
| Aws Secret Access Key      | AWS secret access key parameter for S3-compatible object storage           | `--aws-secret-access-key minio_password`                              | `{"AWS_SECRET_ACCESS_KEY": "minio_password"}`                              | `RCL_AWS_SECRET_ACCESS_KEY=minio_password`                              | `Name: aws-secret-access-key \| Secret Value: minio_password`                              |
| Aws Bucket Name            | AWS bucket parameter for S3-compatible object storage                      | `--aws-bucket-name bridge-xr`                                         | `{"AWS_BUCKET_NAME": "bridge-xr"}`                                         | `RCL_AWS_BUCKET_NAME=bridge-xr`                                         | `Name: aws-bucket-name \| Secret Value: bridge-xr`                                         |
| Aws Endpoint Secure        | Use HTTPS for access to S3-compatible object storage                       | `--aws-endpoint-secure true`                                          | `{"AWS_ENDPOINT_SECURE": "true"}`                                          | `RCL_AWS_ENDPOINT_SECURE=true`                                          | `Name: aws-endpoint-secure \| Secret Value: true`                                          |
| Aws Endpoint Public Secure | Use HTTPS for access to the public url of the S3-compatible object storage | `--aws-endpoint-public-secure true`                                   | `{"AWS_ENDPOINT_PUBLIC_SECURE": "true"}`                                   | `RCL_AWS_ENDPOINT_PUBLIC_SECURE=true`                                   | `Name: aws-endpoint-public-secure \| Secret Value: true`                                   |
| Key Vault Url              | URL to the key vault                                                       | `--key-vault-url https://example.vault.azure.net/`                    | `{"KEY_VAULT_URL": "https://example.vault.azure.net/"}`                    | `RCL_KEY_VAULT_URL=https://example.vault.azure.net/`                    | This parameter cannot be configured via Azure Key Vault                                    |
| Jwt Azure Key Name         | Name of the key in Azure Key Vault used for JWT signing and verification   | `--jwt-azure-key-name jwt-key`                                        | `{"JWT_AZURE_KEY_NAME": "jwt-key"}`                                        | `RCL_JWT_AZURE_KEY_NAME=jwt-key`                                        | `Name: jwt-azure-key-name \| Secret Value: jwt-key`                                        |
| Azure Blob Container Name  | Name of the Azure Blob Storage container                                   | `--azure-blob-container-name ExampleContainer`                        | `{"AZURE_BLOB_CONTAINER_NAME": "ExampleContainer"}`                        | `RCL_AZURE_BLOB_CONTAINER_NAME=ExampleContainer`                        | `Name: azure-blob-container-name \| Secret Value: ExampleContainer`                        |
| Azure Blob Account Name    | Name of the Azure Blob Storage account                                     | `--azure-blob-account-name ExampleAccount`                            | `{"AZURE_BLOB_ACCOUNT_NAME": "ExampleAccount"}`                            | `RCL_AZURE_BLOB_ACCOUNT_NAME=ExampleAccount`                            | `Name: azure-blob-account-name \| Secret Value: ExampleAccount`                            |
| Azure Blob Account Key     | Account key for the Azure Blob Storage account                             | `--azure-blob-account-key ExampleKey`                                 | `{"AZURE_BLOB_ACCOUNT_KEY": "ExampleKey"}`                                 | `RCL_AZURE_BLOB_ACCOUNT_KEY=ExampleKey`                                 | `Name: azure-blob-account-key \| Secret Value: ExampleKey`                                 |
| Azure Blob Account URL     | URL of the Azure Blob Storage account                                      | `--azure-blob-account-url https://example.blob.core.windows.net/`     | `{"AZURE_BLOB_ACCOUNT_URL": "https://example.blob.core.windows.net/"}`     | `RCL_AZURE_BLOB_ACCOUNT_URL=https://example.blob.core.windows.net/`     | `Name: azure-blob-account-url \| Secret Value: https://example.blob.core.windows.net/`     |
| Oidc Keys URL              | URL to fetch OIDC keys used for Microsoft identity platform integration    | `--oidc-keys-url example.com/discovery/v2.0/keys`                     | `{"OIDC_KEYS_URL": "example.com/discovery/v2.0/keys"}`                     | `RCL_OIDC_KEYS_URL=example.com/discovery/v2.0/keys`                     | `Name: oidc-keys-url \| Secret Value: example.com/discovery/v2.0/keys`                     |
| Oidc Keys Refresh Interval | Interval to refresh the OIDC keys                                          | `--oidc-keys-refresh-interval 1h`                                     | `{"OIDC_KEYS_REFRESH_INTERVAL": "1h"}`                                     | `RCL_OIDC_KEYS_REFRESH_INTERVAL=1h`                                     | `Name: oidc-keys-refresh-interval \| Secret Value: 1h`                                     |
| Licensing Host             | Host the licensing server listens on                                       | `--licensing-host`                                                    | `{"LICENSING_HOST": ""}`                                                   | `RCL_LICENSING_HOST=`                                                   | `Name: licensing-host \| Secret Value:`                                                    |
| Licensing Port             | Port the licensing server listens on                                       | `--licensing-port`                                                    | `{"LICENSING_PORT": ""}`                                                   | `RCL_LICENSING_PORT=`                                                   | `Name: licensing-port \| Secret Value:`                                                    |
| Licensing Client Cert Path | Path to the licensing client certificate                                   | `--licensing-client-cert-path /opt/licensing_client_cert.pem`         | `{"LICENSING_CLIENT_CERT_PATH": "/opt/licensing_client_cert.pem"}`         | `RCL_LICENSING_CLIENT_CERT_PATH=/opt/licensing_client_cert.pem`         | `Name: licensing-client-cert-path \| Secret Value: /opt/licensing_client_cert.pem`         |
| Licensing Client Key Path  | Path to the licensing client key                                           | `--licensing-client-key-path /opt/licensing_client_key.pem`           | `{"LICENSING_CLIENT_KEY_PATH": "/opt/licensing_client_key.pem"}`           | `RCL_LICENSING_CLIENT_KEY_PATH=/opt/licensing_client_key.pem`           | `Name: licensing-client-key-path \| Secret Value: /opt/licensing_client_key.pem`           |


# SSO configuration

Steps to configure SSO using Azure

Use this page to configure Azure SSO for Bridge XR.

### Goal

Create an application registration in Microsoft Entra ID that can be used by:

* the web dashboard
* the web player
* the Unity-side login flow where required

### Step 1: open Microsoft Entra ID

Log in to Azure Portal and open **Microsoft Entra ID**.

<figure><img src="/files/yiUreI7DKBX8uf2rLYHY" alt="Open Microsoft Entra ID"><figcaption><p>Open Microsoft Entra ID</p></figcaption></figure>

### Step 2: register a new application

1. Open **App registrations**.
2. Create a new application.
3. Give it a clear name.
4. Click **Register**.

<figure><img src="/files/CI7eImCvAh2eOtXivaqs" alt="Azure app registrations"><figcaption><p>Azure app registrations</p></figcaption></figure>

<figure><img src="/files/U1bgsKga3GaJOqBRmkbo" alt="Create a new Azure application"><figcaption><p>Create a new Azure application</p></figcaption></figure>

### Step 3: add redirect URIs

Add the required redirect URIs for Bridge XR.

#### Mobile and Desktop applications

Add:

`unityhub://editor/cdm.authentication.editoraddons.editorlink/`

<figure><img src="/files/F5Fyqj0xaVgL9TwCGBIf" alt="Select Mobile and Desktop applications"><figcaption><p>Select Mobile and Desktop applications</p></figcaption></figure>

<figure><img src="/files/PxD8cBgDbrKSR5gRRTNU" alt="Configure the Mobile and Desktop redirect URI"><figcaption><p>Configure the Mobile and Desktop redirect URI</p></figcaption></figure>

#### Single-page application for the deployed dashboard

Add:

`https://<YOUR_BASE_URL>/msal-login-popup`

Use your final Bridge XR dashboard base URL.

<figure><img src="/files/NPuYFiINsHiR2IVJC6lE" alt="Add a single-page application redirect URI"><figcaption><p>Add a single-page application redirect URI</p></figcaption></figure>

<figure><img src="/files/THxtNd0nk0PheHaA2Eot" alt="Configure the dashboard redirect URI"><figcaption><p>Configure the dashboard redirect URI</p></figcaption></figure>

#### Local callback

Add:

`http://localhost:51273/StreamingAssets/callback.html`

<figure><img src="/files/8cPFIRFmRx9TX83aKPea" alt="Add the local callback redirect URI"><figcaption><p>Add the local callback redirect URI</p></figcaption></figure>

Once configured, the application should include all required redirect URIs.

<figure><img src="/files/XvYwYvwYxdAhHd6Qvwhl" alt="Completed Azure redirect URI setup"><figcaption><p>Completed Azure redirect URI setup</p></figcaption></figure>

### Step 4: configure token claims

1. Open **Token configuration**.
2. Add the required **Optional Claim**.

<figure><img src="/files/ZiQTMKGSKD9znWTeL9p2" alt="Open Token configuration"><figcaption><p>Open Token configuration</p></figcaption></figure>

<figure><img src="/files/VdpgxHqkJSGYjOJcx7hK" alt="Add the required Optional Claim"><figcaption><p>Add the required Optional Claim</p></figcaption></figure>

### Next step

After Azure is configured, continue with [SSO Integration](/bridge-xr/set-up-bridge-xr/server-deployment/sso-integration).


# Previous version

Archived previous version for internal reference.

| <p>Login to Azure Portal and select Microsoft Entra ID<br><img src="/files/yiUreI7DKBX8uf2rLYHY" alt=""></p> |
| ------------------------------------------------------------------------------------------------------------ |

| <ul><li><p>Register a New Application as follows:<br></p><ul><li><p>Click on ‘App Registration’<br></p><div><figure><img src="/files/CI7eImCvAh2eOtXivaqs" alt=""><figcaption></figcaption></figure></div></li><li><p>Add a corresponding name<br></p><div><figure><img src="/files/U1bgsKga3GaJOqBRmkbo" alt=""><figcaption></figcaption></figure></div></li><li>Click Register.</li></ul></li></ul> |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

<br>

| <ul><li><p>Add Redirect URI as follows:<br></p><div><figure><img src="/files/7i4ZAolCdNgNolm0G0ZJ" alt=""><figcaption></figcaption></figure></div></li></ul><p><br></p><ul><li>Select the Mobile and Desktop applications platform at the bottom:</li></ul><p><img src="/files/F5Fyqj0xaVgL9TwCGBIf" alt="" data-size="original"></p><ul><li>Use the following URL: <code>unityhub://editor/cdm.authentication.editoraddons.editorlink/</code></li><li>Click on Configure<br><img src="/files/PxD8cBgDbrKSR5gRRTNU" alt=""><br></li><li><p>Add another platform using Single page applications:</p><div><figure><img src="/files/NPuYFiINsHiR2IVJC6lE" alt=""><figcaption></figcaption></figure></div></li><li>Use the following URL: <code>https\://\<YOUR\_BASE\_URL>/msal-login-popup</code></li></ul><p>(check with our team since you need your base url for this)<img src="/files/THxtNd0nk0PheHaA2Eot" alt=""><br></p><ul><li>Finally add another one with Single page applications using the following URL: <code><http://localhost:51273/StreamingAssets/callback.html></code><br><img src="/files/8cPFIRFmRx9TX83aKPea" alt=""></li><li>This is how it should look like:<br><img src="/files/XvYwYvwYxdAhHd6Qvwhl" alt=""></li></ul> |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

<br>

| <ul><li>Now go to the Token Configuration section on the left sidebar:<br><img src="/files/ZiQTMKGSKD9znWTeL9p2" alt=""></li><li>Add an ‘Optional Claim’ and set as follows:<br><img src="/files/VdpgxHqkJSGYjOJcx7hK" alt="" data-size="original"></li></ul> |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |


# SSO Integration

Now that you have your Cloud environment set and the SSO configured you need to connect them.

Use this page to connect your Azure SSO setup to the Bridge XR frontend.

### What you need

You should already have:

* a deployed Bridge XR frontend
* a configured Azure application registration
* access to the frontend configuration file provided for your deployment

### Values to copy from Azure

Copy these values from your Azure application and paste them into the provided frontend configuration file.

#### Application ID

Find the **Application ID** in:

`Overview > Essentials`

<figure><img src="/files/GCKKxnv2cj5lW3itCERg" alt="Copy the Application ID from Azure"><figcaption><p>Copy the Application ID from Azure</p></figcaption></figure>

#### Authority URL

Open **Endpoints** and copy the correct **Authority URL** for your setup.

<figure><img src="/files/FZVKKCw0TI6HjfZ9wn8c" alt="Open Azure endpoints"><figcaption><p>Open Azure endpoints</p></figcaption></figure>

<figure><img src="/files/GMgaGhTTJadienllSYaU" alt="Copy the Azure Authority URL"><figcaption><p>Copy the Azure Authority URL</p></figcaption></figure>

### Apply the values

Paste the copied values into the fields required by the provided frontend configuration file.

This connects:

* web dashboard login
* web player login
* the related Bridge XR authentication flow

### After integration

Once the values are applied:

1. redeploy or restart the frontend if required by your setup
2. test login on the deployed dashboard
3. verify the web player authentication flow


# Previous version

Archived previous version for internal reference.

| <p>Find the following information and <strong>paste it where it is required in the provided frontend file.</strong><br></p><ul><li><p>Copy the Application ID in the Overview > Essentials<br></p><div><figure><img src="/files/GCKKxnv2cj5lW3itCERg" alt=""><figcaption></figcaption></figure></div></li><li><p>Then go to Endpoints at the top<br></p><div><figure><img src="/files/FZVKKCw0TI6HjfZ9wn8c" alt=""><figcaption></figcaption></figure></div></li><li><p>Copy the Authority URL (to be checked exactly the one you need)</p><div><figure><img src="/files/GMgaGhTTJadienllSYaU" alt=""><figcaption></figcaption></figure></div></li></ul> |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

<br>


# Previous version

Archived previous version for internal reference.

## Cloud Hosting

### Preparation

| <ul><li>Fill out our <a href="https://form.asana.com/?k=Mj7Z-ZezHQmyppSS_jiJNA&#x26;d=1205786549890494">Onboarding Form</a></li></ul> |
| ------------------------------------------------------------------------------------------------------------------------------------- |

| <ul><li>Define a URL for the dashboard (ex: bridgexr.yourdomain.com) and communicate it as early as possible to the Zoe Immersive team.</li></ul> |
| ------------------------------------------------------------------------------------------------------------------------------------------------- |

{% hint style="warning" %}
Without this the client Apps (VR or Desktop) won't be pointing to your servers.
{% endhint %}

| <ul><li>Configure your SSO to be connected to the Bridge platform (follow <a href="/pages/klrtLpyIX36JBiv1Ka8O">SSO configuration</a>)</li></ul> |
| ------------------------------------------------------------------------------------------------------------------------------------------------ |

### Setup

| <p>Setup Cloud Environment:</p><p>You need the following:<br></p><ul><li>An S3-Compatible object storage or Azure Blob Storage</li><li>A Postgresql database( "Azure Database for PostgreSQL" for example)</li><li>A BridgeXR backend (Running on "Azure Virtual Machines" or "Azure Container Apps" for example)</li><li>A BridgeXR frontend (Running on "Azure Container Apps" for example)</li></ul><p><br><em>Notes:</em><br><em>10GB of storage should be enough for the Backend. And we recommend 2CPU and 2GB of RAM.</em></p><p><em>Object Storage disk size will depend on the number and size of Experiences developers will build (around 50GB should be enough to start with).</em></p><p><em>Database size will depend on the number of participants and frequency of use of the platform (around 20GB for the Database should be enough to start with).</em></p><p><br></p> |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

| <ul><li>Download the Bridge XR Web Files required on <a href="https://zoeimmersive.com/unity/download/#rcl">this page</a>. You need to be logged in with your Zoe for Unity credentials.</li></ul> |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

| <ul><li>Transfer frontend files to a web server hosted on your servers suitable for single page applications (nginx in "Azure Container Apps" for example).</li></ul> |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

| <ul><li>Running the server binary on your linux environment of choice ( "Azure Virtual Machines" or "Azure Container Apps" for example as mentioned above)</li></ul> |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

| <ul><li>Seed the Database (with the script provided by us)</li></ul> |
| -------------------------------------------------------------------- |

| <ul><li>Connect your SSO (see <a href="/pages/6czyPFU2Nb3PufNEsYKh">SSO Integration</a>)</li></ul> |
| -------------------------------------------------------------------------------------------------- |

| <ul><li>Run BridgeXR on your testing environment (if you have one) then pushing it to production.</li></ul> |
| ----------------------------------------------------------------------------------------------------------- |

| <ul><li>Start <a href="/pages/QLwy5wS58a2SCrMEzkjg">adding members</a> and <a href="/pages/xNXc7SQt6K5WCGq7VklO">creating modules</a>!</li></ul> |
| ------------------------------------------------------------------------------------------------------------------------------------------------ |


# Install and Distribute the Bridge XR App

Install, access, and distribute the Bridge XR app across your institution.

Use this page to distribute the installed Bridge XR app for Meta Quest playback.

### Important

The installed **XR app** is only compatible with **Meta Quest headsets**.

{% hint style="info" %}
Browser-based playback uses the **web player** in the web dashboard. It does not require installing the XR app.
{% endhint %}

### What the XR app is for

Participants use the XR app to:

* join modules
* load assigned experiences
* play headset-based experiences
* sign in with institution SSO or guest access where allowed

### Supported headset platform

* **Meta Quest**

### Distribution options

Choose the rollout method that best fits your institution.

* [Meta Horizon Managed Services](https://work.meta.com/help/1780267449441661/?helpref=uf_share)
  * contact us and provide your Organization Key so we can share the application with you
* device management platforms such as [ArborXR](https://arborxr.com/)
* direct `.apk` distribution

### Before rollout

Make sure:

* your Bridge XR platform is already deployed
* your final server URL is configured
* your headset distribution workflow is decided

### Next step

For participant usage, see [Join Modules and Play](/bridge-xr/use-bridge-xr/join-modules-and-play).


# Previous version

Archived previous version for internal reference.

The Bridge XR App is the frontend app client where participants can join modules and play experiences. Supported platforms are:

* VR (Meta Quest 3)
* Desktop (Windows)

It allows users to login with institution SSO credentials or as guests providing only a Full Name.

## Getting access to the App

### VR

Let us know what is your preferred or usual distribution system for VR applications. Here's what we support:

* [Meta Horizon Managed Services](https://work.meta.com/help/1780267449441661/?helpref=uf_share) (soon deprecated due to lack of support from Meta themselves)
  * Please contact us to provide us your Organization Key so we can share the application with you.
* Management services such as [ArborXR](https://arborxr.com/)
* .apk file download

### Desktop

An .exe file is accessible through the Zoe for Unity download page. You can access it using your corresponding credentials.

Once downloaded you can distribute the app as you usually do with other .exe files in your institution.

For using the App please check the [Join Modules and Play page](/bridge-xr/use-bridge-xr/join-modules-and-play).


# Previous version

Archived previous version for internal reference.

Use this section to deploy Bridge XR and prepare access.

This is mainly for IT teams and platform owners.

* Deploy the platform on your infrastructure.
* Configure SSO.
* Distribute the Bridge XR app to supported devices.


# Build with Unity

Use this section to build Bridge XR experiences in Unity and publish them.

This section is mainly for developers, student creators, faculty teams, and external partners.

### Recommended order

1. Install or access **Zoe for Unity**.
2. Add the **Bridge XR integration package**.
3. Build your experience in Unity.
4. Add Bridge XR tracking and completion actions.
5. Upload the experience from Unity.
6. Test the published result.

### What this section covers

* Unity setup for Bridge XR
* Zoe for Unity
* the Bridge XR integration package
* upload from the Bridge Wizard
* testing after upload

{% hint style="info" %}
Published experiences can be targeted for browser-based playback through the **web player**. Headset-based playback uses the installed **Bridge XR App** on **Meta Quest**.
{% endhint %}

### Pages in this section

* [Develop Experiences in Unity](/bridge-xr/build-with-unity/develop-experiences-in-unity)
* [Upload Experiences from Unity](/bridge-xr/build-with-unity/upload-experiences-from-unity)
* [Test Published Experiences](/bridge-xr/build-with-unity/test-published-experiences)


# Develop Experiences in Unity

Use Zoe for Unity and the Bridge XR package to create experiences for your dashboard.

Use this page to prepare a Unity project for Bridge XR.

### What you need

Make sure you have:

* **Zoe for Unity**
* the **Bridge XR integration package**

{% hint style="info" %}
In many institutions, this work may be done by students, faculty teams, or external development partners.
{% endhint %}

### Step 1: install Zoe for Unity

Use the recommended Unity version for Zoe and follow the Zoe installation guide:

[Installing Zoe for Unity](/installation/installing-zoe-for-unity)

<figure><img src="/files/lBwNYnFmgEKySqhyoom0" alt="Installing Zoe for Unity"><figcaption><p>Installing Zoe for Unity</p></figcaption></figure>

### Step 2: install the Bridge XR integration package

After Zoe is installed, add the **Bridge XR integration package** to the same Unity project.

This package connects your Unity project to Bridge XR.

It is used to:

* prepare uploads
* send analytics data
* report experience completion

### Step 3: build your experience with Zoe for Unity

Build your experience in Unity. Use this Help Center whenever needed. Test the experience in Unity until the core flow is stable.

### Step 4: add Bridge XR actions before upload

Before uploading, add the Bridge XR actions needed for tracking.

#### Add Bridge XR scripts

To add actions beyond the standard dropdown list:

1. Click **Add Component**.
2. Search for scripts that begin with `SA_`.

<figure><img src="/files/vp8HIDClKEfGOPBzOD6t" alt="Add Bridge XR scripts in Unity"><figcaption><p>Add Bridge XR scripts in Unity</p></figcaption></figure>

#### Add tracking

For every interaction you want to track, add:

* `SA_StatisticsAction`

<figure><img src="/files/h5roRfgBTqmjSjmFT8ZB" alt="Add SA_StatisticsAction"><figcaption><p>Add SA_StatisticsAction</p></figcaption></figure>

#### Add completion reporting

To let Bridge XR know the experience is complete, add:

* `SA_CompleteAction`

Attach it to the interaction that marks the end of the experience.

<figure><img src="/files/QMPUpO7jvZ9CJnpwkdT5" alt="Add SA_CompleteAction"><figcaption><p>Add SA_CompleteAction</p></figcaption></figure>

### Next step

Once your Unity project is ready, continue with [Upload Experiences from Unity](/bridge-xr/build-with-unity/upload-experiences-from-unity).




---

[Next Page](/llms-full.txt/1)

