When building mixed reality experiences, we highly recommend evaluating your content to offer your users a comfortable and safe experience. Refer to the Health and Safety and Mixed Reality Design guidelines before designing and developing your app. Co-location increases the number of individuals in a shared physical space with restricted visibility of their surroundings. Crowded experiences create safety risks. It is important to be mindful of the occupancy of the playspace for the shared experience being built. Refer to the Shared Spatial Anchors health and safety guidelines for more information. A developer package with health and safety suggestions is also available for easy integration: Shared Spatial Anchors Health and Safety App
Sharing anchors is available for Meta Quest Pro on v47 or higher and for Quest 2 on v49 or higher. Quest 1 does not support sharing anchors.
Overview
Unity-SharedSpatialAnchors demonstrates how to use the Shared Spatial Anchors API. This API is available in the Meta XR Core SDK. The sample app showcases the creation, saving, loading, and sharing of Spatial Anchors. The user-sharing scene uses Photon PUN2 to exchange user IDs and anchor UUIDs and synchronize networked objects. A separate scene demonstrates colocation discovery and group sharing without Photon.
This codebase is available both as a reference and as a template for a game that utilizes Shared Spatial Anchors. The project is under the Unity-SharedSpatialAnchors license unless otherwise specified.
You can find Unity-SharedSpatialAnchors on the Oculus Samples GitHub. Install the Unity version recorded in the project’s ProjectSettings/ProjectVersion.txt (currently 6000.0.66f2) via Unity Hub and enable Android Build Support (OpenJDK, Android SDK and NDK Tools).
Register app on Developer Dashboard and update platform settings
The SharedSpatialAnchors user-sharing scene accesses user IDs through Quest Platform Features. Register an app on the Developer Dashboard and configure the permissions below for that scene. These Platform steps are not required for the ColocationSessionGroups group-sharing scene.
Click Create New App under your developer organization.
Enter a name for your app.
Choose Meta Horizon Store.
From the left navigation, go to Requirements > Data Use Checkup,
Complete Age group self-certification before requesting access to User ID and User Profile platform features.
From the left navigation, go to Development > API. Ensure you’ve selected an app, and then note the number under App ID.
Once you’ve opened the project in Unity, navigate to Meta > Platform > Edit Settings.
Enter the Quest App ID from above in the Meta Quest/2/Pro field.
To test with Link, enable Use Standalone Platform and Use Meta Quest App ID over Rift App ID in Editor, then enter your test user’s credentials.
Under Build Settings, replace the Bundle Identifier with a valid and unique Android package name, like com.yourcompany.ssa_sample. Your app’s anchors will be associated with this package name.
Photon
The SharedSpatialAnchors scene uses Photon PUN2 for multiplayer networking. Skip Photon setup for ColocationSessionGroups, which uses colocation discovery and group sharing. To configure the Photon scene:
On the Dashboard page, follow the prompt to create a new app.
Select Photon SDK: set to Realtime. The sample setup warns against selecting PUN because of a known dashboard issue; the Unity project still uses PUN2.
Name and Description: can be set to anything.
URL: can be left blank.
Add the Photon app ID to the App Id Pun entry in the PhotonServerSettings file under Assets/Photon/PhotonUnityNetworking/Resources/. You can find the PhotonServerSettings from the menu at Window > Photon Unity Networking > Highlight Server Settings.
Pre-configured Project Settings
OVRManager Configuration
The OVRManager component is attached to the OVRCameraRig object in each scene.
OVRManager has the following parameters that must be configured for SSA:
Tracking Origin Type: STAGE
The STAGE tracking origin type will ensure that virtual objects do not move when a re-center event occurs.
Anchor Support: Enabled
Shared Spatial Anchor Support: Required or Supported
The sample app uses Supported because it includes local anchor functionality.
Android Manifest
The Android manifest tool can be used to update your project manifest to support SSA.
Window > Meta > Tools > Create store-compatible AndroidManifest.xml
The following permissions are required for SSA and passthrough to work in your app:
The manifest tool adds these declarations from the OVRManager project configuration. For the ColocationSessionGroups discovery workflow, Colocation Session Support must also be Supported or Required. Regenerating the manifest adds com.oculus.permission.USE_COLOCATION_DISCOVERY_API. See Colocation Discovery for details.
User-sharing scene features
In SharedSpatialAnchors, you should be in a passthrough environment with virtual representations of your right and left controllers.
Control Panel
A control panel follows your left controller. You can use your right controller to interact with it and press menu buttons with the white dot on your controller. Create or join a room using the control panel to get started.
The main menu of the control panel includes the following functions:
Toggle Anchor Creator: Toggles anchor creation mode. When enabled, an anchor preview is visible on your right hand. Upon pressing the trigger, you can place a new Spatial Anchor into the scene.
Load Local Anchors: Downloads and instantiates any anchors that are saved to the headset.
Spawn Networked Cube: Spawns a cube just above the menu. The cube is visible and grabbable by all players in the room. Grabbing the cube transfers network ownership to the player that grabs it.
Photon Info Panel: Shows the photon room that the player has connected to, the current connection status, and a list of users in the room.
Logging Panel: The right half of the menu is used for logging (for debug purposes). You can press the arrow buttons on the bottom right to navigate multiple pages of logs.
Anchor Panel
When an anchor spawns, the anchor panel appears.
The anchor panel includes the following functions:
Save Anchor Locally: Saves the anchor to your local headset. Load the anchor by selecting the Load Local Anchors option from the control panel.
Hide Anchor: Deletes the anchor from the scene, but remains saved in your local headset storage if you saved it. You can respawn it by selecting the Load Local Anchors option on the control panel.
Erase Anchor: Deletes the anchor from the scene and erases the saved file in local storage. You’ll no longer be able to load the anchor.
Share Anchor: Shares the anchor with all other users that are connected to the room and any new users that join the room.
Align to Anchor: Realigns your headset’s coordinate system to be based on this anchor transform. This enables co-location when multiple users align to the same Shared Anchor. You’ll notice the networked cube appears in the same position for all users.
Sample app architecture
The sample uses the Meta XR Core SDK for spatial anchors, shared anchors, colocation sessions, and passthrough. The user-sharing scene also uses MR Utility Kit for world-lock alignment.
Scenes
Assets/Scenes/Menu.unity: Select a sharing workflow and manage local sample data.
Assets/Scenes/SharedSpatialAnchors.unity: Share anchors to users using Photon PUN2 to exchange user IDs and anchor UUIDs. Align peers with MRUK world locking and synchronize networked cubes.
Assets/Scenes/ColocationSessionGroups.unity: Advertise or discover nearby sessions with OVRColocationSession, share and load anchors by group UUID, and align peers without Photon. An arbitrary group UUID can also be used to test group sharing without discovery.
The older Shared Scene, CoLocatedSafety, and AnchorCaching scenes are not part of the current sample. For a walkthrough of the maintained scenes, see the Unity Shared Spatial Anchors sample overview.
Scripts
Scripts are located under Assets/Scripts/:
Script
Purpose
SharedAnchor.cs
Per-anchor saving, erasing, user sharing, and alignment
SharedAnchorLoader.cs
Load locally persisted anchors first, then request missing shared anchors from the cloud
PhotonAnchorManager.cs
Manage Photon rooms and exchange anchor identifiers
SharedAnchorControlPanel.cs
Control the user-sharing scene’s UI
ColoDiscoMan.cs
Advertise and discover colocation sessions and share anchors to groups
ColoDiscoAnchor.cs
Control each anchor in the group-sharing scene
Alignment.cs
Implement MRUK world locking and classic tracking-space alignment
LocallySaved.cs
Persist anchor UUIDs in JSON, separately for each scene
SampleController.cs
Manage scene configuration and anchor placement
Search for // KEY API CALL in these scripts to find the relevant SDK calls.
Anchor alignment
Different devices start with different tracking-space origins. Loading the same shared anchor gives each device a reference to the same physical point, but your app must also place non-anchored content in a common coordinate system.
The sample demonstrates two approaches in Alignment.cs:
MRUK world locking: In the user-sharing scene, the host exchanges the anchor’s original pose through Photon. Clients use MRUK.Instance.SetCustomWorldLockAnchor to align to that reference.
Classic tracking-space alignment: In the group-sharing scene, Alignment.SetOrigin adjusts the camera rig’s tracking space relative to the shared anchor. It can also reposition existing non-anchored objects to preserve their placement during alignment.
Align peers before spawning non-anchored networked objects, or adjust existing objects when changing the origin. Sharing an anchor does not synchronize the subsequent movement or ownership of gameplay objects; your application supplies that networking.
Loading persisted anchors
LocallySaved records UUIDs for later sessions. SharedAnchorLoader first attempts OVRSpatialAnchor.LoadUnboundAnchorsAsync for local copies, then uses LoadUnboundSharedAnchorsAsync for missing shared anchors. After localization, it instantiates and binds an OVRSpatialAnchor in the same frame.
This persistence is part of the maintained sample’s loading flow; it does not require the older dedicated AnchorCaching scene.