ハイライト
RealityKit Debugger は実行中アプリの 3D スナップショットを取得し、Xcode で Entity Hierarchy、3D ビューポート、Inspector の 3 カラムレイアウトを表示 — View Debugger が UIKit をデバッグするように spatial アプリをデバッグできます。
主要内容
3D アプリで最も困ることの一つ:コードでは確かに配置したのに、実行すると見えない、位置がおかしい、形が歪む。以前は print と経験で推測するしかありませんでした。RealityKit の Entity 階層と Transform 継承関係は複雑で、目視では問題箇所が分かりません。
Apple は Xcode に RealityKit Debugger を追加しました。View Debugger と同じ動作:デバッグエリアの “Capture Entity Hierarchy” ボタンをクリックして現在シーンの 3D スナップショットを取得し、Xcode で 3 カラムビューを開きます — 左に Entity Hierarchy ツリー、中央に 3D ビューポート、右に Inspector パネル。任意の Entity を選択すると 3 カラムが連動して階層位置、空間位置、全 Component プロパティを表示します。
このセッションは「植物園アプリをロボットナイトクラブに改造」する実プロジェクトで、4 種類の最も一般的な 3D バグの特定方法をデモ:Transform 継承による形状変形、Component 書き戻し忘れによる動作異常、レンダリングパイプライン問題によるコンテンツ欠落、カスタム Component で Debugger にデバッグ情報を追加する方法。いずれも 3D 開発の高頻度問題で、可視化ツールがあればトラブルシューティング効率が全く異なります。
詳細
1. Transform 継承による変形
ディスコボールの線が潰れて見えます。Debugger で Outline Entity を選択すると、Inspector プレビューではモデル自体は変形せず、Transform コンポーネントの scale も均一な 1。問題は自分ではなく祖先ノードにあります。上に向かって確認:Background は正常、Support Entity の Transform に Y 軸方向の大きな scale — Support は形状形成のために伸長されていますが、変形を全子孫に伝播します。
修正:Support と Background を親子関係から兄弟関係に変更(06:50)。
// 修正前:Background は Support の子ノードで、Y 軸 scale を継承していた
support.addChild(background)
// 修正後:Background と Support は兄弟ノードで、どちらも discoBall の下にある
discoBall.addChild(background)
キーポイント:
support.addChild(background)は Background が Support の Y 軸 scale 変形を継承discoBall.addChild(background)に変更すると Background は discoBall の Transform のみ継承、Support の影響を受けない- 2 つの Entity はシーン内で依然接続して見えるが、Transform は相互干渉しない
2. Component 変更後の書き戻し忘れ
テレポートシステムはロボットを継続生成すべきですが何も現れません。Debugger で Teleporter Entity を確認 — Component は全て存在。Teleportation Center の ControlCenterComponent を見ると countdown 値が常に初期値 — System の update が効いていないことを示します。
コードに戻ると問題:System は毎回 update で controlCenter.countdown を変更しますが、変更後の Component が Entity に書き戻されていません(10:18)。
// TeleportationSystem.update で抜けていた重要な手順
// 5. Save updated component back to the entity
controlCenterEntity.components[ControlCenterComponent.self] = controlCenter
キーポイント:
- RealityKit の Component は値型(struct)、Entity から取得して変更後は書き戻し必須
- SwiftUI の
@State修正の考え方と異なり、見落としやすい - Debugger は一時停止時点のリアルタイム状態をキャプチャ、countdown 値が変わらない = System が Entity 上のデータを実際に更新していない
3. レンダリング問題による不可視コンテンツ
カウンターの 9 本のオイルボトルのうち 1 本だけ可視。Debugger で各ボトルを逐一確認すると問題はそれぞれ異なります:カウンター下方の位置(遮蔽)、シーン境界外(クリップ)、scale 過大でカメラがモデル内部(三角形は外表面のみレンダリング)、Entity 未有効、AnchoringComponent 残留だが対応 ARKit anchor なし、ModelComponent が誤った Entity に、Material の opacityThreshold が 1 で opacity が 1 未満(ボトル全体不可視)、Mesh 法線反転(3D ツールで修正)、またはシーンへの追加自体を忘れ。
修正は全コピペコードを作成ループに置き換え(18:15)。
private func stockBottles(placementRadius: Float) -> Entity {
let bottleRadius: Float = 0.003
let bottleHeight: Float = 0.022
let angleIncrement: Float = -12
let outOfStockBrands: Set = [3]
let bottleGroup = Entity()
bottleGroup.name = "Bottle Group"
bottleGroup.position = [0, 0.04, 0]
bottleGroup.orientation = .init(angle: 180 * (.pi / 180), axis: [0, 1, 0])
var bottleMaterial = PhysicallyBasedMaterial()
bottleMaterial.baseColor = .init(tint: .green)
bottleMaterial.blending = .transparent(opacity: .init(floatLiteral: 0.5))
for i in 0..<9 {
let angle = Angle2D(degrees: angleIncrement * Float(i))
let bottleMesh = MeshResource.generateCylinder(height: bottleHeight, radius: bottleRadius)
let bottle = ModelEntity(mesh: bottleMesh, materials: [bottleMaterial])
bottle.name = "BT\(i)"
bottle.position = pointOnCircumference(angle: angle, radius: placementRadius, y: bottleHeight / 2)
if outOfStockBrands.contains(i) {
bottle.components[OutOfStockComponent.self] = OutOfStockComponent()
}
bottleGroup.addChild(bottle)
}
return bottleGroup
}
キーポイント:
- ループ作成で手動コピペを代替し、「コピー時のパラメータ誤り」を根源排除
pointOnCircumferenceで位置を統一計算、手動座標ミスを回避outOfStockBrandsは Set で欠品管理、ロジックが明確- セッション推奨:シーンレイアウトは可能な限り Reality Composer Pro で、純コード配置より信頼性高い
4. カスタムデバッグ可視化
ロボットがナイトクラブにテレポート後、ダンスフロアに向かわず立ち止まります。開発者は #if DEBUG ブロックでデバッグ Entity を追加:各不可視アトラクターに半透明シリンダー可視化、カスタム AttractorDebugComponent で Inspector に状態とターゲット参照、DanceSystemDebugComponent で Swift Chart 円グラフ(UIImage プロパティとして保存)。
Debugger で全アトラクターが attracting 状態と一目で分かる — 通常 1 つのみのはず。アトラクターの attractor 参照リンクをクリックしてターゲットロボットにジャンプ、Newcomer Component が削除されていないことが判明、全アトラクターが同じロボットをロック。修正は 1 行のみ(22:48)。
// 4. Untag them as a Newcomer
visitor.components[Newcomer.self] = nil
キーポイント:
- カスタム Component プロパティは Inspector に自動表示、Entity 参照はクリック可能リンクに
UIImage型プロパティは Inspector で画像表示可能、Swift Chart 状態円グラフなど- デバッグシステム全体を
#if DEBUGブロック内に、Release ビルドではコンパイラが完全除去
重要ポイント
-
何をするか:RealityKit Debugger を日常デバッグフローに組み込み、「表示異常」の第一反応は print ではなく Entity Hierarchy キャプチャ。なぜ価値があるか:3D シーンの階層関係と Transform 継承はコード読解ではほぼ推測不能、可視化ツールが問題階層を直接特定。始め方:visionOS シミュレータでアプリ実行、Xcode デバッグエリアの “Capture Entity Hierarchy” をクリック。
-
何をするか:Entity に意味のある
nameプロパティを設定、例:"Disco Ball"でデフォルト空文字列ではなく。なぜ価値があるか:Debugger の Hierarchy ツリーは名前表示、名前空の Entity はトラブルシューティング時に識別不能。始め方:Entity 作成直後にentity.name = "説明的な名前"を設定。 -
何をするか:
#if DEBUGブロックでカスタム System にデバッグ可視化と Inspector Component を追加。なぜ価値があるか:ECS System が複雑になるほど実行時状態の追跡が困難、カスタム Component で Debugger がビジネスロジック状態を直接表示。始め方:セッションのDanceSystemDebugComponentパターンを参考 — カスタム Component でカウンターと Entity 参照を保持、UIImageプロパティでチャート表示も可能。 -
何をするか:シーンレイアウトは Reality Composer Pro を優先、純コード 3D アセット配置を避ける。なぜ価値があるか:セッションの 9 ボトル 9 種類のエラーは全てコード内手動座標とプロパティ設定由来、ビジュアルエディタが根源からこの類の問題を削減。始め方:Reality Composer Pro でアセット配置・設定、エクスポート後
Entity.load(named:)でロード。
関連セッション
- Discover RealityKit APIs for iOS, macOS, and visionOS — RealityKit クロスプラットフォーム API の最新更新と新機能概覧
- Compose interactive 3D content in Reality Composer Pro — Reality Composer Pro でインタラクティブ 3D シーンを構築・プレビュー
- Build a spatial drawing app with RealityKit — visionOS で RealityKit API を使った spatial 描画アプリ構築
- Create enhanced spatial computing experiences with ARKit — spatial コンピューティング体験開発の最新 ARKit API
- Create custom environments for your immersive apps in visionOS — visionOS イマーシブアプリ向けカスタム環境の作成
コメント
GitHub Issues · utterances