Contents

Configure your visionOS app for sharing with people nearby

Create shared experiences for people wearing Vision Pro in the same room and those on FaceTime.

Overview

SharePlay in visionOS helps people share activities together — for example, viewing a movie, listening to music, playing a game, or sketching ideas on a whiteboard. Starting in visionOS 26, SharePlay supports inviting nearby people who are wearing Apple Vision Pro to join a group activity. The system presents participants differently based on how they join the activity:

  • Nearby participants appear naturally via passthrough.

  • FaceTime participants who are wearing Apple Vision Pro appear as spatial Personas.

  • Participants on other devices appear in a standard FaceTime window.

Both nearby participants and spatial Personas can move spatially, make eye contact, and reference virtual content during an activity, enhancing the feeling of being together in the same room. Get your visionOS app ready for sharing with people nearby by reviewing the APIs below that help you create seamless connections among people — whether they’re in the same room or on FaceTime.

Verify your app’s nearby-sharing behavior

SharePlay doesn’t require apps to distinguish between nearby and FaceTime participants. The GroupActivities APIs you use to manage group sessions, exchange messages, and position content treat all participants the same. Your app doesn’t need separate code to support nearby participants, so it typically already works when sharing with people nearby, but confirm the following during testing:

Spatial assumptions

Confirm that your app doesn’t rely on the system to position nearby participants in specific locations. SharePlay can dynamically reposition spatial Personas (FaceTime participants), but not physical people (nearby participants). If your app requires participants to be in specific locations, guide nearby participants to move to those locations using visual cues, like position markers.

Share Window menu

Confirm that your activity is listed in the new Share Window menu located next to the window bar. This is critical for the discovery of your app’s SharePlay activity. The easiest way to add your activity to the Share Window menu is to include a hidden ShareLink in your app.

ShareLink(item: BoardGameActivity(), preview: SharePreview("Play Together"))
    .hidden()

For more information, see Presenting SharePlay activities from your app’s UI.

Activity activation

If your app implements a custom SharePlay button, confirm that your app supports initiating an activity when there isn’t an active FaceTime call. For visionOS, update the button’s action handler to always call activate(), which now presents the new Share Window menu, and remove any checks for isEligibleForGroupSession that guard activating the activity.

Distinguish between nearby and FaceTime participants

To observe when participants join and leave an activity use activeParticipants. To determine if a Participant is nearby, use isNearbyWithLocalParticipant:

func observeParticipants(session: GroupSession<BoardGameActivity>) async {
    for await activeParticipants in session.$activeParticipants.values {
        // The set of nearby participants, excluding the local participant.
        let nearbyParticipants = activeParticipants.filter {
            $0.isNearbyWithLocalParticipant && $0.id != session.localParticipant.id
        }
    }
}

Position content relative to participants

Because nearby participants can join a group activity, you can no longer assume a spatial participant’s pose (position and orientation) matches their seat’s pose. When SharePlay applies a SpatialTemplate, it moves FaceTime participants using their spatial Persona to their assigned seats so their pose matches their seat’s pose. SharePlay can’t move a nearby participant, so the participant’s pose can be different from their seat’s pose.

  • To observe the state of remote FaceTime and nearby participants use remoteParticipantStates.

  • To observe the state of the local participant, who is wearing Vision Pro, use localParticipantStates.

  • To position content relative to a participant, position the content relative to pose.

  • To position content relative to a participant’s seat, position the content relative to pose.

Synchronize entity transforms across devices

To achieve consistent positioning of RealityKit entities across multiple devices in an immersive space during a SharePlay session, enable support for a group immersive space using supportsGroupImmersiveSpace. When enabled, visionOS automatically ensures entities with identical transforms appear in the same relative location for all participants, including both nearby and remote participants.

Group immersive spaces handle this spatial consistency for entities with identical transforms, but keep in mind that SharePlay doesn’t automatically synchronize changes to your app’s state. Your app needs to maintain visual consistency across participants’ devices and you have full control over what actions are synchronized. For example, if your app displays a cube with a position of [0, 1, 0] at launch, the shared coordinate system causes everyone to see that cube at the same position. However, if a participant creates a new cube, your app needs to use the GroupSessionMessenger to notify the other participants to reflect this change.

For more information, see Synchronizing data during a SharePlay activity.

Incorporate the real world in your app’s shared context

When you’re sharing with people who are nearby, you may want to anchor shared virtual content to objects in the real world. Unlike remote SharePlay with spatial Personas, when you’re sharing with someone nearby, the real world is part of your shared context. To enable this, ARKit has support for sharing world anchors that appear in the exact same place for all nearby participants.

To make a WorldAnchor shareable with nearby participants, initialize the anchor with the sharedWithNearbyParticipants property set to true with the init(originFromAnchorTransform:sharedWithNearbyParticipants:) initializer. ARKit then shares that anchor with all nearby SharePlay participants via the anchorUpdates async sequence.

Your app can then attach an entity to that anchor to place it in the exact same world location for all nearby participants.

// Create a shared world anchor with ARKit.

func setUp(session: ARKitSession, provider: WorldTrackingProvider) async throws {
    try await session.run([provider])
}

func createAnchor(
    at transform: simd_float4x4, 
    provider: WorldTrackingProvider
) async throws {
    // Create a world anchor with `sharedWithNearbyParticipants` set to `true`.
    let anchor = WorldAnchor(
        originFromAnchorTransform: transform,
        sharedWithNearbyParticipants: true
    )
    try await provider.addAnchor(anchor)
}

func observeWorldTracking(provider: WorldTrackingProvider) async {
    for await update in provider.anchorUpdates {
        switch update.event {
            case .added, .updated, .removed:
            // Updates with shared anchors from others.
            let anchorIdentifier = update.anchor.id
        }
    }
}

See Also

Spatial activities