docs.unity3d.com
Search Results for

    Show / Hide Table of Contents

    Shared anchors

    OpenXR Meta provides a shared anchors API that enables you to share anchors between colocated users. The shared anchors feature enables users within the same physical space to share and load anchors to their devices. You can use this API to enable local multiplayer experiences with a shared frame of reference created by shared anchors. For example, you can use the shared anchors feature to play a virtual board game on top of the same table in the physical environment.

    Sharing anchors works by creating a group ID and sharing anchors with that ID. To share anchors, you must first Set the group ID. The following sections describe the shared anchors feature in more detail.

    Check support

    To learn which Quest devices support shared anchors, refer to Meta’s shared spatial anchors Device requirements.

    You can also use MetaOpenXRAnchorSubsystem.isSharedAnchorsSupported to check whether a device supports shared anchors, as shown in the following code example:

    using UnityEngine.XR.OpenXR.Features.Meta;
    
    public class CheckSharedAnchorsSupportSample
    {
        void CheckIsSharedAnchorsSupported(ARAnchorManager anchorManager)
        {
            // First get a reference to the MetaOpenXRAnchorSubsystem
            var metaAnchorSubsystem =
                (MetaOpenXRAnchorSubsystem)anchorManager.subsystem;
    
            if (metaAnchorSubsystem.isSharedAnchorsSupported == Supported.Supported)
            {
                // Shared anchors is supported
            }
        }
    }
    

    Set the group ID

    To set the group ID for your current session, generate a new SerializableGuid and set the MetaOpenXRAnchorSubsystem.sharedAnchorsGroupId property as shown in the following code example:

    using UnityEngine.XR.OpenXR.Features.Meta;
    
    public class SetSharedAnchorsGroupIdSample
    {
        void SetSharedAnchorsGroupId(ARAnchorManager anchorManager)
        {
            // First get a reference to the MetaOpenXRAnchorSubsystem
            var metaAnchorSubsystem =
                (MetaOpenXRAnchorSubsystem)anchorManager.subsystem;
    
            metaAnchorSubsystem.sharedAnchorsGroupId =
                new SerializableGuid(Guid.NewGuid());
        }
    }
    
    Note
    Important

    Set the group ID to a non-empty GUID, i.e. new SerializableGuid(Guid.NewGuid()), as Meta's OpenXR runtime doesn't allow sharing anchors to an empty group ID.

    Share the group ID

    Share your group ID with colocated users of your app so they can share and load anchors from the same group. Generate a new ID for each session to prevent users in previous sessions accessing shared anchors in your current session.

    Note

    Don't use shared anchors as an alternative to saving anchors. To re-use shared anchors across multiple sessions, save the anchor before sharing, and re-share the anchor in subsequent sessions to a new group ID.

    Share group IDs between devices

    AR Foundation doesn't provide a networking solution for messaging GUIDs between users on different devices. The AR Foundation Samples GitHub repository contains example code that uses Netcode for GameObjects to demonstrate one way to share GUIDs between devices to get you started.

    Share anchor

    Once you have set the group ID, all subsequent calls to TryShareAnchorAsync or TryShareAnchorsAsync will share anchors with that group.

    Most apps will only need one group per physical location of colocated users. However, you can also share with multiple groups if necessary by changing the active group ID at any time.

    To share an anchor, use the ARAnchorManager.TryShareAnchorAsync extension method as shown in the following code example:

    using UnityEngine.XR.OpenXR.Features.Meta;
    
    public class SingleShareAnchorSample
    {
        async void ShareAnchorAsync(ARAnchorManager anchorManager, ARAnchor anchor)
        {
            var resultStatus = await anchorManager.TryShareAnchorAsync(anchor);
            if (resultStatus.IsError())
            {
                // Handle error
                return;
            }
    
            // Anchor was successfully shared.
        }
    }
    

    Batch share anchors

    You can share a batch of anchors with the ARAnchorManager.TryShareAnchorsAsync extension method as shown in the following code example:

    using UnityEngine.XR.OpenXR.Features.Meta;
    
    public class BatchShareAnchorsSample
    {
        async void ShareAnchorsAsync(
            ARAnchorManager anchorManager, IEnumerable<ARAnchor> anchors)
        {
            var results = new List<XRShareAnchorResult>();
            await anchorManager.TryShareAnchorsAsync(anchors, results);
    
            foreach (var result in results)
            {
                if (result.resultStatus.IsSuccess())
                {
                    // Anchor with results.anchorId was successfully shared.
                }
                else
                {
                    // Anchor with results.anchorId failed to share.
                }
            }
        }
    }
    

    Meta defines its OpenXR API such that the entire batch either succeeds or fails to share together. This means if one anchor fails to share, then all anchors will fail to share.

    Load shared anchors

    Once you have set the group ID, you can load all shared anchors from the group with the ARAnchorManager.TryLoadAllSharedAnchorsAsync extension method as shown in the following code example:

    using UnityEngine.XR.OpenXR.Features.Meta;
    
    public class LoadAllSharedAnchorsSample
    {
        async void LoadAllSharedAnchorsAsync(ARAnchorManager anchorManager)
        {
            var loadedXRAnchors = new List<XRAnchor>();
            var resultStatus = await anchorManager.TryLoadAllSharedAnchorsAsync(
                loadedXRAnchors, OnIncrementalResultsAvailable);
    
            if (resultStatus.IsError())
            {
                // Handle error here.
                return;
            }
    
            // Request completed successfully.
        }
    
        void OnIncrementalResultsAvailable(ReadOnlyListSpan<XRAnchor> xrAnchors)
        {
            foreach (var xrAnchor in xrAnchors)
            {
                // To get the GameObject of the loaded anchor,
                // keep track of the xrAnchor's trackableId to
                // know which anchors in
                // `ARAnchorManager.trackablesChanged.added`
                // were added as a result of this load request.
                var anchorId = xrAnchor.trackableId;
            }
        }
    }
    

    If TryLoadAllSharedAnchorsAsync returns a successful XRResultStatus, the List<XRAnchor> passed in will be populated with all anchors that were successfully loaded. Use the XRAnchor.trackableId to know which anchors were loaded as shared anchors when ARAnchorManager.trackablesChanged is invoked.

    To receive notifications about loaded shared anchors before ARAnchorManager.trackablesChanged is invoked, rely on the incremental results callback. The final result from TryLoadAllSharedAnchorsAsync isn't guaranteed to complete before any ARAnchorManager.trackablesChanged events are invoked for loaded shared anchors.

    Incremental load results

    The third input parameter of the ARAnchorManager.TryLoadAllSharedAnchorsAsync extension method allows you to pass a callback method, which the provider will invoke whenever anchors are incrementally loaded. This enables you to work with anchors as soon as they become available without waiting for the entire load request to complete. You should use the incremental results callback to ensure you're notified when an anchor has loaded before ARAnchorManager.trackablesChanged is raised. To ignore the incremental results, pass null for the callback.

    The incremental results callback passes a ReadOnlyListSpan<XRAnchor> when invoked that provides a read-only slice of the List<XRAnchor> output list passed into the ARAnchorManager.TryLoadAllSharedAnchorsAsync extension method.

    Shared anchors expiration

    At the time of writing, shared anchors remain shared with the group ID for 30 days since the last successful share. You can't otherwise stop sharing an anchor once it's been shared. Refer to Meta's Shared Anchors documentation for the most recent information regarding anchor expiration.

    In This Article
    Back to top
    Copyright © 2025 Unity Technologies — Trademarks and terms of use
    • Legal
    • Privacy Policy
    • Cookie Policy
    • Do Not Sell or Share My Personal Information
    • Your Privacy Choices (Cookie Settings)