Claude CodeでvisionOSアプリを開発する手順
Claude CodeでvisionOSアプリを作る際の、ウィンドウ・ボリューム・イマーシブ空間の実装手順とXcodeとの役割分担を、公式ドキュメントのコード例で確認します。
visionOSはApple Vision Pro向けのオペレーティングシステムです。ウィンドウ・ボリューム・イマーシブ空間という3種類のシーンをSwiftUIで組み合わせてアプリを作ります。Claude CodeはこれらのSwift・SwiftUI・RealityKitのコードを書き換え、ターミナルからのビルド確認を担当します。ただしプロジェクトの作成とSimulatorでの表示確認は、引き続きXcodeのGUI操作として残ります。
visionOS開発を始める前に確認すること
visionOS向けの開発は、Apple Silicon搭載のMacがなければ始まりません。公式ドキュメントも、visionOS開発にはApple Siliconを積んだMacが必要だと明記しています。加えてXcode本体とvisionOS SDKが必須です。既存のiPhone・iPadアプリがあるなら、ターゲットにvisionOSを追加するだけで移行に着手できます。
新規プロジェクトはXcodeのテンプレート選択画面で作ります。ここで初期シーンの種類を選びます。2Dコンテンツが中心ならWindow、3Dコンテンツが中心ならVolumeを選び、あとからImmersive Spaceを追加することもできます。3Dアセットを扱うなら、Reality Composer Proのプロジェクトファイルを同時に含めておくと、USDZアセットや独自の3Dシーンをアプリに組み込みやすくなります。
3Dコンテンツ自体はRealityKitとReality Composer Proで構築し、RealityViewで表示します。RealityKitは物理的な照明条件に自動で合わせて影を落とせる3Dレンダリングエンジンで、サーフェスとジオメトリのシェーダーを記述する業界標準規格MaterialXにも対応しています。没入体験の中で周囲の物理空間と統合したいときはARKitを使います。Plane Estimation・Scene Reconstruction・Image Anchoring・World Tracking・Skeletal Hand Trackingといった機能が使えます。床に物を弾ませたり壁に水を飛ばしたりする表現も実現できます。
初めてvisionOS開発に触れる場合は、公式が配布するサンプルアプリで基礎を確認するのも近道です。Hello Worldはウィンドウ・ボリューム・イマーシブ空間の3つを一通り使う教材です。BOT-anistはウィンドウとボリュームを組み合わせたマルチプラットフォームアプリの例として公開されています。
Claude CodeとXcodeの役割分担
Claude Codeはファイルの読み書きとターミナル操作を軸にしたコーディングエージェントです。visionOS開発では、SwiftUIのシーン宣言やビューのコード、RealityKitのコードを書く作業を任せられます。ターミナルからxcodebuildを呼び出してのビルド確認も可能です。
一方で、新規プロジェクトのテンプレート選択、Simulatorでの表示・ジェスチャー確認、Reality Composer Proでの3Dシーン編集はXcodeのGUI操作のまま残ります。コード編集とビルド確認、プロジェクト作成と目視確認という線引きです。作業の境目を先に共有しておくと、Claude Codeへの指示に迷いが減ります。
| 作業 | 担当 |
|---|---|
| Xcodeプロジェクトの新規作成 | 担当Xcode(GUI) |
| WindowGroup・ImmersiveSpaceなどのシーン宣言の編集 | 担当Claude Code |
| xcodebuildによるコマンドラインビルド | 担当Claude Code |
| Simulatorでの表示・ジェスチャー確認 | 担当Xcode(GUI) |
| Reality Composer Proでの3Dシーン作成 | 担当Xcode(GUI) |
| USDZアセットを読み込むコードの実装 | 担当Claude Code |
XcodeにClaudeを直接組み込む方法としてはClaude for Xcodeの使い方もあります。ただしこれはApple自身がXcodeの「Intelligence」設定に組み込んだ別の機能で、契約体系もインストール方法もClaude Code CLIとは異なります。
ウィンドウを実装する
visionOSアプリはWindowGroupから始まります。次のコードは、ウィンドウの背景に半透明の黒を敷きつつ、イマーシブ空間を1つ宣言する最小構成です。
@main
struct MyApp: App {
var body: some Scene {
WindowGroup {
ContentView()
.background(.black.opacity(0.8))
}
ImmersiveSpace(id: "Immersive") {
ImmersiveView()
}
}
}ウィンドウの初期位置はdefaultWindowPlacementモディファイアで指定できます。次の例は、画面の表示範囲を基準に下端から140ポイントの位置へウィンドウを置きます。
Window("Status", id: "status") {
StatusView()
}
.windowResizability(.contentSize)
.defaultWindowPlacement { content, context in
let displayBounds = context.defaultDisplay.visibleRect
let size = content.sizeThatFits(.unspecified)
let verticalOffset = 140
let position = CGPoint(
x: displayBounds.midX - (size.width / 2),
y: displayBounds.maxY - size.height - verticalOffset)
return WindowPlacement(position: position, size: size)
}ただしvisionOSでは、ウィンドウが表示された後の位置やサイズをアプリ側から直接操作できません。人がその場でウィンドウを動かしたりリサイズしたりする自由を、システム側が確保する設計です。
ボリュームで3Dコンテンツを追加する
3Dコンテンツが主役のシーンにはボリュームを使います。WindowGroupに.windowStyle(.volumetric)を指定するだけで、そのシーンは3D空間として描画されます。
struct MyApp: App {
var body: some Scene {
WindowGroup {
Model3D("balloons")
}.windowStyle(style: .volumetric)
}
}ボリュームのサイズは、ポイントではなくメートル単位で指定するのが公式の推奨です。次の例は1辺1メートルの立方体を確保します。
WindowGroup(id: "globe") {
Globe()
}
.windowStyle(.volumetric)
.defaultSize(width: 1, height: 1, depth: 1, in: .meters)メートル指定が推奨される理由は明快です。ボリュームは通常のウィンドウと違って動的スケーリングをせず、固定スケールで描画されます。そのためUIというより物理的なオブジェクトとして人の前に現れます。RealityViewを組み合わせれば、RealityKitで構築した3Dシーンをボリューム内にそのまま表示できます。
人の視線とジェスチャーにどう対応するか
visionOSでの入力は、マウスやタッチとは前提が異なります。公式ドキュメントは3種類の入力経路を挙げています。
- 間接入力: 視線で対象を示し、両手または片手の親指と人差し指を触れ合わせて操作を始めます
- 直接入力: 指が画面上の項目と同じ位置に来たときにシステムが操作を認識します
- キーボード入力: 接続したマウス・トラックパッド・キーボードで項目を操作し、メニューコマンドやジェスチャーを実行します
SwiftUIは標準のジェスチャーを組み込みでサポートしているため、多くの操作はビューにジェスチャー修飾子を足すだけで動きます。標準の枠を超えたカスタムジェスチャーが必要なときだけ、ARKitで直接組み立てます。
イマーシブ空間を実装する
人の周囲を部分的、あるいは完全にコンテンツで覆いたいときはイマーシブ空間を使います。ImmersiveSpaceシーンを宣言し、openImmersiveSpaceアクションで開きます。
struct NewSpaceButton: View {
@Environment(\.openImmersiveSpace) private var openImmersiveSpace
var body: some View {
Button("View Orbits") {
Task {
await openImmersiveSpace(id: "orbits")
}
}
}
}イマーシブ空間には3種類のスタイルがあります。
| スタイル | 挙動 |
|---|---|
| mixed(既定) | 挙動周囲のパススルー映像を残しつつ仮想コンテンツを重ねる |
| full | 挙動パススルーを完全に隠し、アプリのコンテンツだけを表示する |
| progressive | 挙動パススルーを隠す度合いを人が段階的に調整できる |
スタイルを切り替え可能にするには、immersionStyle(selection:in:)モディファイアで候補を渡します。
@main
struct MyImmersiveApp: App {
@State private var currentStyle: ImmersionStyle = .full
var body: some Scene {
WindowGroup() {
ContentView()
}
ImmersiveSpace(id: "solarSystem") {
SolarSystemView()
}.immersionStyle(selection: $currentStyle, in: .full)
}
}アプリ起動時にいきなりイマーシブ空間を開きたい場合は、Info.plistのUIApplicationPreferredDefaultSceneSessionRoleキーにUISceneSessionRoleImmersiveSpaceApplicationを設定します。起動直後に人を没入させすぎないよう配慮することも、公式のデザインガイドラインが求めている点です。
ウィンドウと空間の遷移を正しい順序で書く
ウィンドウもイマーシブ空間も、アプリに残る最後の1つのシーンとしてはプログラムから閉じられません。開始ボタンを押したらウィンドウを閉じてイマーシブ空間へ切り替える、というよくあるパターンには順序の注意が要ります。
Button("Start") {
Task {
await openImmersiveSpace(id: "chessboard")
dismissWindow(id: "start") // Runs after the space opens.
}
}openImmersiveSpaceは非同期に実行されます。dismissWindowをTaskの外に置くと、空間が開き終わる前に実行される恐れがあります。その場合、空間は開くのにウィンドウが閉じずに残るという不具合になります。Claude Codeにこの種の遷移コードを書かせるときは、awaitで完了を待ってから閉じる処理を置く順序を指示に明記すると事故を防ぎやすくなります。
シーンタイプの使い分け早見表
| シーン | 向くコンテンツ | 特徴 |
|---|---|---|
| Window | 向くコンテンツ2Dが中心のUI | 特徴従来のビュー・コントロールをそのまま使える |
| Volume | 向くコンテンツ3Dが中心の単一オブジェクト | 特徴メートル単位の固定スケールで描画される |
| Immersive Space | 向くコンテンツ周囲を覆う没入体験 | 特徴mixed・full・progressiveの3スタイル、同時に1つのみ |
よくあるつまずき
複数シーンを同時に開けない
visionOSは既定では複数シーンの同時表示を許可しません。openWindowやopenImmersiveSpaceを呼んでも何も起きないときは、Info.plistのUIApplicationSupportsMultipleScenesキーがtrueになっているか確認します。falseのままだとSwiftUIはアクションを無視し、ランタイムエラーだけをログに残します。
Unityで3Dコンテンツを作る場合の選択肢
visionOSはRealityKitだけでなくUnityにも対応しています。既存のUnityプロジェクトをvisionOS向けに持ち込む場合は、Unity公式MCPサーバーをClaude Codeで使う方法で扱っているMCP連携が使えます。
Claude Codeにプロジェクト作成そのものは頼めない
Xcodeのテンプレート選択(File > New > Project)はGUI操作で完結する工程で、Claude Codeが代替する経路ではありません。プロジェクトを作成した後、SwiftのコードやInfo.plistの編集をClaude Codeに任せる、という順序で進めるのが現実的です。Claude Code自体のインストール手順はClaude Codeのインストールガイドにまとめています。
描画が重いと感じたらInstrumentsで確認する
ボリュームは固定スケール、イマーシブ空間は広い範囲の3Dコンテンツと、シーンごとに描画コストのかかり方が異なります。処理が重いと感じたら、まずInstrumentsのRealityKit Traceテンプレートでボトルネックを特定します。そのうえで3Dコンテンツの複雑さやシーンの構成をClaude Codeに調整させるのが、公式が推奨する進め方です。
まとめ
visionOSアプリは、WindowGroupやImmersiveSpaceといったSwiftUIのシーン宣言を軸に、Window・Volume・Immersive Spaceの3つを組み合わせて作ります。Claude CodeはこれらのSwift・RealityKitコードの編集とxcodebuildでのビルド確認を担当します。プロジェクト作成やSimulatorでの表示確認は、Xcode側のGUI操作として残ります。複数シーンの同時表示にはInfo.plistの設定が要り、イマーシブ空間は同時に1つしか開けません。この2点を踏まえてコードを書けば、遷移まわりの不具合は避けやすくなります。