Instruction

Setting the Scene

With an Immersive experience app, you’re responsible for everything that appears on the screen. You can use an Immersive Space for a VR game, to create a focused experience for your user, to provide a new environment to work in, or to take the user to a new place to experience.

When you open an Immersive view, the system will hide all visible apps. All of the normal mechanics of visionOS disappear: PassThrough video is disabled, as your content fills the view, and only the user’s hands are visible when they’re raised in front, if configured in the app. It’s recommended that you give the user time to transition from the Spaced Space into your app, and once there, you give them an easy exit. Using the Digital Crown, the user can dial-back the experience if enabled.

Initially, you’ll show the user a Window with some way to enter the space. From a RealityView, you’ll call openImmersiveSpace asynchronously and then display an ImmersiveSpace bound to your WindowGroup. You’ll provide a binding for the effective immersion style: automatic, full, mixed, or progressive.

AutomaticImmersionStyle is the default immersion style. With FullImmersionStyle, the app is completely immersed in an unbounded space with no pass-through video. MixedImmersionStyle includes other app content and pass-through video. ProgressiveImmersionStyle provides a radial portal and allows users to adjust from mixed to full immersion.

Button("Open ImmersiveSpace") {
  Task {
    let result = await openImmersiveScene(id: "ImmersiveSpace")
    if case .error = result {
      print("An error occurred")
    }
  }
}

You can attach Hashable, Codable present data to an ImmersiveSpace. You can also configure the app to open to an ImmersiveSpace at launch in the Info.plist.

When the app starts the immersive view, visionOS will warn users to be aware of their surroundings.

To exit the Immersive Space, you call dismissImmersiveScene(), and the user will return to their familiar surroundings. While in the Immersion, visionOS creates elements approximately a meter away from the user. visionOS also creates a region 1.5 meters around the user, so if they physically move beyond that, Passthrough video becomes enabled. That way, the user can see the furnishings and obstacles around them.

Building on VR technologies, you can employ a skybox image to project surrounding elements on reflective objects you’re using. For example, a shiny orb will reflect the surroundings provided by the skybox, such as nearby windows or bright-colored objects. You can use an image to create a light source to project light onto your objects.

By default, the user drops into a lightless 360° void. You can put them inside a sphere and light the sphere with a panoramic image painted on the inside towards the user. They’ll seem to be inside a starfield, a new city, or a forest with mountains off in the distance.

The illusion is that they’ll see the horizon, sky, mountains, or the surface of the Moon. Adding creature sounds, or spatial audio clips complete the illusion. In later lessons, you’ll look at spatial audio and other lighting effects.

Your app won’t be complete without a new visionOS 3D app icon. The app icon can be similar to an iOS app icon. However, the Shared Space provides the hover effect and a little parallax motion as the user moves around while focused on the icon. You achieve this by adding up to three images: a background image, a middle image, and a front image, like your logo. You’ll polish off this simple app with a visionOS-style logo.

Note: Xcode 26 introduced the new Icon Composer application for creating Liquid Glass an app icon file. visionOS apps don’t use Icon Composer app icons at the time of writing. You can add a .icon file to a multi-platform app, and it will be used by iOS. However your visionOS app won’t use it.

In the demo video, you’ll look at creating an immersive space, adding objects to the scene, animating them in a special way, and lighting them with image-based lighting.

See forum comments
Download course materials from Github
Previous: Introduction Next: Demo Part 1