Develop

Unity Space Sharing sample

Updated: May 11, 2026

Overview

This sample demonstrates the complete Mixed Reality Utility Kit (MRUK) Space Sharing workflow for synchronizing real-world scene entities across multiple devices. A host loads local scene data, shares room anchors to Meta’s cloud under a group UUID, and guests download that shared data with automatic world alignment. The sample uses Photon PUN for networking, but the MRUK Space Sharing APIs are networking-agnostic.

What you will learn

  • Loading local scene data from the device using MRUK.Instance.LoadSceneFromDevice()
  • Sharing room anchors to Meta’s cloud using MRUK.ShareRoomsAsync()
  • Loading shared rooms on guest devices using MRUK.Instance.LoadSceneFromSharedRooms()
  • Automatically aligning guest worlds to the host’s floor anchor using the alignmentData parameter
  • Integrating MRUK Space Sharing with a networking solution by transmitting group UUIDs and alignment data

Requirements

  • Meta Quest 2, Quest 3, or Quest 3S
  • A development environment configured for Quest development (see Set up your development environment)
  • Space Setup data captured on each test device
For Unity version requirements, Photon configuration, and build prerequisites, see the sample README.

Get started

Clone the repository from https://github.com/oculus-samples/Unity-SpaceSharing and open the project in Unity. Follow the sample README to configure your Photon Realtime app ID and Meta Horizon Store app. Open the Menu.unity scene and build to your Quest device. Launch the app, select “MRUK Space Sharing w/ Photon (PUN)”, and create or join a Photon room to begin exploring Space Sharing.

Explore the sample

The sample consists of two scenes and a suite of scripts that manage MRUK API calls, Photon networking, and UI workflows.
File / SceneWhat it demonstratesKey concepts
Assets/Scenes/Menu.unity
Main menu launcher
Simple scene loader
Assets/Scenes/LocalSpaceSharing.unity
Space sharing scene with UI panels
Host/guest coordination, room lifecycle
Assets/Scripts/MRSceneManager.cs
Core MRUK Space Sharing API calls
LoadSceneFromDevice(), ShareRoomsAsync(), LoadSceneFromSharedRooms()
Assets/Scripts/PhotonRoomManager.cs
Photon PUN room lifecycle and custom property sync
Room creation, property versioning, event firing
Assets/Scripts/LocalSpaceSharingUI.cs
UI button callbacks and auto-load logic
Guest auto-load on property update
Assets/Scripts/PhotonExtensions.cs
Custom Photon serializers for Guid and Pose
Photon type registration
Assets/Scripts/ExposedAnchorPrefabSpawner.cs
Wrapper around MRUK’s AnchorPrefabSpawner
Anchor mesh visualization toggle
Assets/Scripts/AlignPlayer.cs
Manual floor anchor alignment (no longer used)
Previous manual alignment pattern
Assets/Scripts/Sampleton.cs
Central singleton for scene management and logging
Platform SDK initialization, nickname handling
Assets/Scripts/SampleExtensions.cs
Utility extensions for room presence and logging
IsInLoadedRoom(), error formatting
OculusProjectConfig.asset
Project-level OVR settings
Shared anchor support, scene support, passthrough
AndroidManifest.xml
Android permissions
USE_ANCHOR_API, IMPORT_EXPORT_IOT_MAP_DATA, USE_SCENE

Runtime behavior

When you run the sample, you start at a main menu. Select “MRUK Space Sharing w/ Photon (PUN)” to load the space sharing scene. The UI shows a lobby panel with “Create New Room” and “Find Room” buttons, which remain disabled until Photon connects to the master server.
After creating or joining a room, the room panel displays controls for the Space Sharing workflow. As the host, press “Load or Scan Space” to load your local scene data — the system prompts you to run Space Setup if you have no captured data. Gray anchor meshes appear representing your walls, furniture, and floor. Press “Share This Space” to upload the anchors to Meta’s cloud. Guests joining the same Photon room automatically receive the group UUID and room UUIDs via room properties and can press “Load Shared Spaces” to download the shared scene. Late joiners also receive the current shared data upon joining. The shared scene entities appear in each guest’s view, aligned to the host’s physical space.

Key concepts

Three-step Space Sharing workflow

MRUK Space Sharing follows a three-step host/guest pattern:
  1. The host loads local scene data with MRUK.Instance.LoadSceneFromDevice().
  2. The host shares anchors to Meta’s cloud with MRUK.ShareRoomsAsync() and transmits the group UUID to guests via the networking layer.
  3. Guests call MRUK.Instance.LoadSceneFromSharedRooms() with the group UUID to download and align the shared anchors.
// Host shares (simplified)
var result = await mruk.ShareRoomsAsync(mruk.Rooms, groupId);
For complete implementation, see MRSceneManager.cs.

Group UUID as the sharing key

The group UUID is the coordination point for all Space Sharing operations. The sample supports three generation strategies: Guid.NewGuid() for a fresh UUID each session, Application.buildGUID so all instances of the same build share one group, or a hardcoded GUID for a fixed sharing namespace. The chosen UUID is transmitted to other clients via Photon room properties.
See GetSharedGroupId() in MRSceneManager.cs.

Automatic world alignment via alignmentData

When guests call LoadSceneFromSharedRooms(), passing the host’s floor anchor pose as alignmentData enables automatic world alignment. The sample captures the host’s floor pose and transmits it via Photon room properties. MRUK uses this data to transform the loaded room so that non-anchored virtual objects appear at the same world positions for all clients.
// Guest loads with alignment
var result = await MRUK.Instance.LoadSceneFromSharedRooms(
    roomIds, groupUuid, alignmentData: hostAlignment, removeMissingRooms: true
);
See LoadSharedSceneImpl() and SetHostAlignment() in MRSceneManager.cs.

Photon room properties for data transmission

The sample transmits the group UUID, room UUIDs, and floor pose via Photon room custom properties. It uses a version counter (“ver” key) to prevent conflicts when multiple clients publish updates simultaneously. When the host publishes, all connected clients (including late joiners) receive property updates and can trigger their own load operations.
See PublishRoomData() and OnRoomPropertiesUpdate() in PhotonRoomManager.cs.

Custom Photon serializers for Guid and Pose

Photon PUN does not natively serialize System.Guid or UnityEngine.Pose. The sample registers custom serializers using Protocol.TryRegisterType() at startup. Guid serializes as 16 raw bytes; Pose serializes as 7 floats (3 for position, 4 for rotation).
See PhotonExtensions.cs.

Extend the sample

  • Replace Photon with another networking solution by implementing the same group UUID and alignment data transmission pattern.
  • Add virtual objects anchored to scene entities and observe how they align across clients.
  • Implement a lobby system that shows which rooms have shared spaces available.