【VisionOS】Immersive Space Progressive の作成方法について
はじめに
こんにちは!システム開発部のYです。
Immersive Space Progressiveについて調査したため、まとめていきます。
Appleのサンプルアプリ「Destination Video」にそのような実装があったので、それを参考にしています。
環境
Swift Version: 5.9.2
Xcode: 15.2
visionOS: 1.0
macOS: 14.3.1
Immersive Space とは
https://developer.apple.com/documentation/visionos/adding-3d-content-to-your-app
Immersive Spaceは、空間内にアプリケーションをどのように表示するかを定義する表現方法です。
以下の3つのスタイルがあります。
Mixed immersion
パススルーの上にアプリのコンテンツを融合させて、表示する
Full immersion
パススルーを表示せずに、アプリのコンテンツのみを表示する
Progressive immersion
Mixed immersionと、Full immersionの中間のようなスタイル。Digital Crownを操作することで、没入度の調整をすることができる。今回はこの、Progressive immersionを使用します。
Immersive Space Progressive の作成
動画のように前面に背景が表示され、Digital Crownを操作すると没入度を調整することができます。
Assetの追加
Progressiveで表示したい背景の画像を追加します。
App.swift
テンプレートからプロジェクトを作成、App構造体にImmersiveSpaceを追加をします。
IDは、”testImmersiveSpace”とします。
今回は、Progressiveにするため、ImmersionStyleに.progressiveを設定します。
import SwiftUI
@main
struct sampleVisionOSApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
ImmersiveSpace(id: "testImmersiveSpace") {
ImmersiveSpaceView()
}
// Immersion Styleを.progressiveに設定すると、ユーザーは Digital Crown を使用して体験を調整できるようになる
.immersionStyle(selection: .constant(.progressive), in: .progressive)
}
}
ContentView.swift
NewProjectから作成後のサンプルコードに、Buttonを追加しています。
Buttonが押され、isPressedの変更がかかります。
.onChangeで変更を検知し、trueの場合、openImmersiveSpaceを実行します。
引数のidに”testImmersiveSpace”を指定することで、ImmersiveSpaceを表示します
import SwiftUI
import RealityKit
import RealityKitContent
struct ContentView: View {
@Environment(\.openImmersiveSpace) var openImmersiveSpace
@Environment(\.dismissImmersiveSpace) var dismissImmersiveSpace
@State var isPressed = false
var body: some View {
VStack {
Button(isPressed ? "Space Closed" : "Space Opened") {
isPressed.toggle()
}.foregroundColor(isPressed ? .red : .green)
Model3D(named: "Scene", bundle: realityKitContentBundle)
.padding(.bottom, 50)
Text("Hello, world!")
}
.padding()
.onChange(of: isPressed) { (_, new) in
Task {
if new {
await openImmersiveSpace(id: "testImmersiveSpace")
} else {
await dismissImmersiveSpace()
}
}
}
}
}
#Preview(windowStyle: .automatic) {
ContentView()
}
ImmersiveSpaceView.swift
TextureResource.loadAsync(named: destination.imageName)を使用して、指定された画像ファイルを非同期で読み込んでいます。画像はAssetで追加した名前を設定しています。
読み込んだ画像を「UnlitMaterial」に設定します。
その後、画像を設定したMaterialを球体に貼り付けてます。
球体のスケールに(-1, 1, 1)を掛けることで、球体が水平方向に反転し、内側から画像が見えるようにしています。
import SwiftUI
import RealityKit
import Combine
struct ImmersiveSpaceView: View {
@State var cancellable: AnyCancellable?
var body: some View {
RealityView { content in
let rootEntity = Entity()
cancellable = TextureResource.loadAsync(named: "beach_scene").sink(
receiveCompletion: {
switch $0 {
case .finished: break
case .failure(let error): assertionFailure("\(error)")
}
},
receiveValue: { texture in
var material = UnlitMaterial()
// 読み込んだテクスチャをUnlitMaterialに設定
material.color = .init(texture: .init(texture))
// ModelComponentを設定
rootEntity.components.set(ModelComponent(
mesh: .generateSphere(radius: 1E3),
materials: [material]
))
// スケールを反転して球体を内部から見えるようにする
rootEntity.scale *= .init(x: -1, y: 1, z: 1)
// 球体の位置を少し上に移動させる
rootEntity.transform.translation += SIMD3<Float>(0.0, 1.0, 0.0)
})
content.add(rootEntity)
}
}
}
#Preview {
ImmersiveSpaceView()
}
まとめ
Immersive Space Progressiveの作成方法についてまとめました。
Progressiveを使用すると、仮想空間に視界を包み込みつつユーザーの操作で没入度を調整することができるため、ユーザーは自身の好みに合わせて仮想体験の深さをコントロールできます。
これにより、没入感のある面白いアプリケーションを作成することが可能です。
この記事がお役に立てれば幸いです。また、間違っている点などありましたら、教えていただけると幸いです。
参考リンク
この記事が気に入ったらサポートをしてみませんか?