ハイライト
visionOS の空間コンピューティングプラットフォームは、SwiftUI、RealityKit、ARKit というおなじみの 3 つのフレームワークを基盤にしています。Window、Volume、Full Space という 3 種類のコンテナにより、開発者は同じコードベースで 2D ウィンドウから完全没入型体験まで構築できます。
主要内容
3 種類の空間コンテナ
visionOS の中核設計は 3 種類のコンテナを中心にしています(01:27):
Window(ウィンドウ)
Window は SwiftUI の Scene で、サイズ変更や再レイアウトができ、macOS のウィンドウに近い挙動をします。一方で 2D と 3D コンテンツの混在に対応しており、ひとつのウィンドウ内にボタンと 3D モデルを同時に配置できます。
Volume(ボリューム)
Volume は Shared Space で 3D コンテンツを表示する固定境界付きコンテナです(02:07)。盤面や地球儀のように、さまざまな角度から見られる 3D コンテンツに適しています。Volume も SwiftUI Scene であり、3D の描画には RealityKit を使います。
Full Space(全空間)
Full Space はアプリが視野全体を占有し、ほかのアプリを非表示にします(02:47)。Full Space では、Skeletal Hand Tracking などの ARKit API を利用できます。Full Space には 3 種類の没入スタイルがあります:
- Mixed:現実環境(passthrough)の上に仮想コンテンツを重ねる
- Full:現実環境を完全に隠し、仮想コンテンツだけを表示する
- Progressive:最初は現実環境を表示し、ユーザーが Digital Crown で没入度を調整できる
自然なインタラクション
visionOS のインタラクションは目と両手を基盤にしています(04:30):
- ボタンを見て指で軽くタップすると選択できる
- 3D 空間内のボタンに直接手を伸ばして触れられる
- システムは tap、long press、drag、rotate、zoom などのジェスチャをサポートする
- SwiftUI のジェスチャ API は RealityKit Entity とシームレスに統合される
ARKit の Skeletal Hand Tracking により、ユーザーの手を仮想のクラブにしてボウリングを行うような、より複雑なジェスチャも実現できます(05:36)。
プライバシー優先のアーキテクチャ
visionOS のプライバシー設計は厳格です(07:47)。アプリはセンサーデータへ直接アクセスできず、システムが生データをイベントや視覚的なヒントに変換してからアプリへ渡します。たとえば:
- システムはユーザーの目と手の 3D 位置を把握しているが、アプリには touch イベントだけを渡す
- ユーザーが特定のビューを注視すると、システムは hover 効果を描画するが、ユーザーがどこを見ているかはアプリに伝えない
- シーン理解(壁や家具の検出)や Skeletal Hand Tracking へのアクセスが必要な場合、システムは先にユーザーの許可を求める
詳細
開発ツールチェーン
Xcode は visionOS 向けに完全な開発ツールを提供します(09:05):
Xcode Preview
Preview Canvas は 3D プレビューに対応しており、コード編集中に RealityKit シーンの描画結果やアニメーション効果を直接確認できます(09:34)。Object Mode では 3D レイアウトをすばやくプレビューし、コンテンツがビュー境界内に収まっているか確認できます。
Simulator
Simulator ではキーボード、マウス、ゲームコントローラを使ってシーン内を移動し、観察できます。3 種類のシミュレーションシーンが用意され、それぞれ昼と夜のライティングがあります(11:03)。
RealityKit Trace
Instruments 15 には RealityKit Trace テンプレートが追加され、GPU、CPU、システム消費電力への影響を分析し、フレームのボトルネックを追跡し、送信された三角形の総数やシミュレーションされた RealityKit Entity 数を確認できます(12:24)。
Reality Composer Pro
新しい 3D コンテンツ編集ツールで、次に対応します:
- パーティクルシステム(雲、雨、火花などの効果)
- 空間オーディオのプレビュー
- 物理ベースのマテリアル(PBR)
- MaterialX のカスタムマテリアルノードグラフ(14:32)
Window を作成する
Window は WindowGroup で作成し、2D と 3D コンテンツを混在させられます:
import SwiftUI
import RealityKit
@main
struct HelloWorldApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
struct ContentView: View {
var body: some View {
VStack {
Text("Hello, World!")
// ウィンドウに 3D コンテンツを埋め込む
Model3D(named: "Satellite") { model in
model
.resizable()
.aspectRatio(contentMode: .fit)
} placeholder: {
ProgressView()
}
}
}
}
キーポイント:
Model3DはImageに似ており、RealityKit で描画される 3D モデルを読み込んで表示する- ウィンドウ内の 3D コンテンツは z 軸方向に浮き出し、奥行き感を加える
DragGestureで 3D Entity を直接ドラッグできる
Volume を作成する
Volume は windowStyle を .volumetric に設定して作成します:
@main
struct EarthApp: App {
var body: some Scene {
WindowGroup(id: "earth") {
EarthView()
}
.windowStyle(.volumetric)
.defaultSize(width: 0.6, height: 0.6, depth: 0.6, in: .meters)
}
}
キーポイント:
.windowStyle(.volumetric)は WindowGroup を Volume にするdefaultSizeはボリュームの幅、高さ、奥行きを指定し、単位には.pointsまたは.metersを使える- Volume のコンテンツは境界内に収める必要がある
- Shared Space に適しており、ほかのウィンドウと共存できる
RealityView 和 Attachments
RealityView は SwiftUI 内で RealityKit Entity を管理する中核ビューです:
import SwiftUI
import RealityKit
struct GlobeView: View {
var body: some View {
RealityView { content, attachments in
// make closure: Entity を作成してルート Entity に追加
if let earth = try? await Entity(named: "Earth") {
content.add(earth)
}
// attachment をシーンに追加
if let pin = attachments.entity(for: "pin") {
pin.position = [0, 0.5, 0]
content.add(pin)
}
} update: { content, attachments in
// update closure: 状態が変化したときに呼び出される
} attachments: {
// attachments closure: SwiftUI ビューを定義
Attachment(id: "pin") {
Image(systemName: "mappin")
.font(.largeTitle)
.foregroundColor(.red)
}
}
}
}
キーポイント:
makeclosure はビュー作成時に一度実行され、Entity の初期化に使うupdateclosure は SwiftUI の状態が変化したときに呼び出されるattachmentsは SwiftUI ビューを 3D シーンに配置できる Entity へ変換する- 各 attachment には一意の
idが必要
Full Space を作成する
Full Space は ImmersiveSpace Scene 型で作成します:
@main
struct SpaceApp: App {
@State private var immersiveStyle: ImmersionStyle = .full
var body: some Scene {
WindowGroup {
ContentView()
}
ImmersiveSpace(id: "outerSpace") {
OuterSpaceView()
}
.immersionStyle(selection: $immersiveStyle, in: .full, .mixed, .progressive)
}
}
struct ContentView: View {
@Environment(\.openImmersiveSpace) var openImmersiveSpace
@Environment(\.dismissImmersiveSpace) var dismissImmersiveSpace
var body: some View {
Button("Enter Space") {
Task {
await openImmersiveSpace(id: "outerSpace")
}
}
}
}
キーポイント:
ImmersiveSpaceは入室可能な Full Space シーンを定義する.immersionStyleは没入スタイルを設定し、デフォルトは.mixedopenImmersiveSpace環境値は空間を開くために使うdismissImmersiveSpace環境値は空間を閉じるために使う- 没入体験に入るかどうかをユーザーが選べるボタンを用意するのがおすすめ
ジェスチャと 3D Entity のインタラクション
SwiftUI のジェスチャは RealityKit Entity を直接ターゲットにできます:
Model3D(named: "Satellite") { model in
model
.resizable()
.aspectRatio(contentMode: .fit)
}
.placeholder {
ProgressView()
}
.gesture(
DragGesture()
.targetedToEntity(named: "Satellite")
.onChanged { value in
// ドラッグ値に基づいて Entity を移動
value.entity.position = value.convert(value.location3D, from: .local, to: .parent)
}
)
キーポイント:
.targetedToEntity(named:)はジェスチャを特定の Entity に結び付けるvalue.location3Dは 3D 空間内のドラッグ位置を取得するconvert(_:from:to:)は座標空間間で位置を変換する
既存 App から移行する
visionOS は 3 種類の移行パスをサポートします(15:40):
- 互換モード:iPad/iPhone App は変更なしで動作し、システムがウィンドウの拡大縮小や回転を自動処理する
- 再コンパイル:Xcode で visionOS ターゲットを追加して再コンパイルすると、ネイティブの余白、サイズ、再レイアウトが得られる
- 新規設計:visionOS App テンプレートを使い、Window または Volume から始めて空間コンピューティングの能力を活用する
重要ポイント
Model3D で既存 App に奥行き感を加える
- 何をするか:既存の SwiftUI App のビューに
Model3Dを追加し、3D 製品モデルを表示する - 取り組む価値:RealityKit コードを書かなくても、
Imageと同じような簡単さで UI に空間的な奥行きを加えられる - 始め方:USDZ モデルを Xcode プロジェクトへドラッグし、
Model3D(named: "モデル名")で読み込む
回転して確認できる 3D 商品表示を作る
- 何をするか:Volume で 3D 商品モデルを表示し、ユーザーがさまざまな角度から確認できるようにする
- 取り組む価値:Volume は 3D コンテンツ表示に向いており、ユーザーはジェスチャで回転や拡大縮小ができ、2D 画像より直感的に理解できる
- 始め方:
WindowGroupを作成し、.windowStyle(.volumetric)を設定して、その中のRealityViewで商品モデルを読み込む
段階的に没入する瞑想 App を設計する
- 何をするか:App 起動時は Shared Space にコントロールパネルを表示し、開始をタップしたら Full Space に入り、Progressive 没入スタイルでユーザー自身が没入度を調整できるようにする
- 取り組む価値:Progressive 没入はユーザーに制御権を与え、軽い没入から完全な没入へ段階的に移行できるため、不快感を減らせる
- 始め方:
ImmersiveSpaceでシーンを作成し、.immersionStyle(selection: $style, in: .progressive)を設定する
RealityView Attachments で 3D 地図マーカーを作る
- 何をするか:3D 地球儀や地図上で、SwiftUI ビューをマーカー(pin)として使う
- 取り組む価値:Attachments により、慣れた SwiftUI コードで 3D シーン内の UI 要素を作成でき、新しい UI フレームワークを学ぶ必要がない
- 始め方:
RealityViewのattachmentsclosure でマーカービューを定義し、makeclosure でattachments.entity(for: "id")を取得して配置する
関連セッション
- Build spatial experiences with RealityKit — RealityKit で空間体験を構築
- Meet ARKit for spatial computing — 空間コンピューティングにおける ARKit の活用
- Develop your first immersive app — 初めての没入型 App を開発
コメント
GitHub Issues · utterances