ハイライト
ARKit は visionOS 2.0 で Room Tracking を追加し、従来は幾何頂点のみだった mesh データを部屋境界の意味論を持つ RoomAnchor にアップグレード。app が部屋ごとに仮想コンテンツを切り替え可能に。
主要内容
visionOS app を作る開発者は皆同じ問題に直面します:ARKit は mesh 頂点と平面アンカーを提供しますが、コードは「ユーザーが今どの部屋にいるか」を判断できません。座標と幾何で推測するしかなく、推測が外れると仮想コンテンツが間違った場所に配置されます。Super Fruit Ninja がフルーツの残骸を床に散らせるのは scene understanding のおかげですが、昨年の API は平面と mesh しか認識できず、「部屋」レベルの意味論は不可能でした。
今年 ARKit は Room Tracking を追加し、ユーザーが現在いる部屋の境界、壁と床の幾何を直接伝え、リビングから寝室へ移動するとデータソースを自動切り替えします。同時に Object Tracking が追加され、USDZ モデルで実物体を登録すると ARKit が位置と向きを継続追跡。教育や産業など、実物に仮想コンテンツを重ねるシナリオに適しています。Plane Detection に Slanted アライメントも追加され、斜面を検出可能に。さらに World Tracking は暗所で自動的に向きのみの追跡に降级し、Hand Tracking は display-rate 出力と手の予測をサポートしてインタラクション遅延を低減。
詳細
Room Tracking
RoomTrackingProvider は今年追加された DataProvider で、world sensing 認可が必要です。現在の部屋の RoomAnchor と非同期 anchor 更新シーケンスを提供します(03:35)。
// RoomTrackingProvider
@available(visionOS, introduced: 2.0)
public final class RoomTrackingProvider: DataProvider, Sendable {
/// The room which a person is currently in, if any.
public var currentRoomAnchor: RoomAnchor? { get }
/// An async sequence of all anchor updates.
public var anchorUpdates: AnchorUpdateSequence<RoomAnchor> { get }
...
}
キーポイント:
currentRoomAnchorは現在の部屋のアンカーを直接返す。nilは ARKit が閉鎖空間を認識していないanchorUpdatesは非同期シーケンスで、部屋切り替えイベントの監視に適する- RoomTrackingProvider は現在所在部屋の anchor データのみ更新し、すべての履歴部屋を同時更新しない
各 RoomAnchor には部屋の幾何情報が含まれます(04:20):
@available(visionOS, introduced: 2.0)
public struct RoomAnchor: Anchor, Sendable, Equatable {
/// True if this is the room which a person is currently in.
public var isCurrentRoom: Bool { get }
/// Get the geometry of the mesh in the anchor's coordinate system.
public var geometry: MeshAnchor.Geometry { get }
/// Get disjoint mesh geometries of a given classification.
public func geometries(of classification: MeshAnchor.MeshClassification) ->
[MeshAnchor.Geometry]
/// True if this room contains the given point.
public func contains(_ point: SIMD3<Float>) -> Bool
/// Get the IDs of the plane anchors associated with this room.
public var planeAnchorIDs: [UUID] { get }
/// Get the IDs of the mesh anchors associated with this room.
public var meshAnchorIDs: [UUID] { get }
}
キーポイント:
isCurrentRoomでこのアンカーがユーザーの現在部屋か判断し、部屋ごとの仮想コンテンツ切り替えに使用geometryは通常の mesh anchor より部屋境界に沿った mesh を返すgeometries(of:)は分類(壁/床)ごとに分離した幾何を返し、オクルージョンや壁全体の仮想ポータルに有用contains(_:)で 3D 点が部屋内か判断。world tracking と組み合わせ「特定の部屋に入ったときだけトリガー」を実現planeAnchorIDsとmeshAnchorIDsで現在部屋に属するアンカーをフィルタし、部屋外データへの高コスト計算を回避
Object Tracking
Object Tracking はまず CreateML で ReferenceObject を生成し、ランタイムでロードして追跡を開始する必要があります(08:06)。
// Object tracking
Task {
do {
let url = URL(fileURLWithPath: "/path/to/globe.referenceobject")
let referenceObject = try await ReferenceObject(from: url)
let objectTracking = ObjectTrackingProvider(referenceObjects: [referenceObject])
} catch {
// Handle reference object loading error.
}
...
}
キーポイント:
- ReferenceObject はファイル URL または Bundle からロード
- 1 つの ObjectTrackingProvider で複数 ReferenceObject を同時追跡可能
- ロード失敗は例外をスローし、catch で処理が必要
session を開始して状態を監視(08:27):
let session = ARKitSession()
Task {
do {
try await session.run([objectTracking])
} catch {
// Handle session run error.
}
for await event in session.events {
switch event {
case .dataProviderStateChanged(_, newState: let newState, _):
if newState == .running {
// Ready to start processing anchor updates.
}
...
}
}
}
キーポイント:
session.run()は async で await が必要- DataProvider が
.running状態になってから anchor 更新を処理可能 session.eventsで状態変化を非同期監視
追跡結果は ObjectAnchor 形式で返されます(08:43):
// ObjectAnchor
@available(visionOS, introduced: 2.0)
public struct ObjectAnchor: TrackableAnchor, Sendable, Equatable {
/// An axis-aligned bounding box.
public struct AxisAlignedBoundingBox: Sendable, Equatable {
...
}
/// The bounding box of this anchor.
public var boundingBox: AxisAlignedBoundingBox { get }
/// The reference object which this anchor corresponds to.
public var referenceObject: ReferenceObject { get }
}
キーポイント:
boundingBoxは検出物体の軸平行境界ボックスを提供。center、extent、最小/最大座標を取得可能referenceObjectは一致した ReferenceObject を指し、元の USDZ ファイルパスを取得可能- Object Tracking は静止配置の物体のみ追跡。運動中の物体は不可
World Tracking の照度降级
暗所では ARKit が完全追跡から向きのみの追跡に自動降级。SwiftUI に worldTrackingLimitations 環境値が追加され app に通知(11:03):
struct WellPreparedView: View {
@Environment(\.worldTrackingLimitations) var worldTrackingLimitations
var body: some View {
...
.onChange(of: worldTrackingLimitations) {
if worldTrackingLimitations.contains(.translation) {
// Rearrange content when anchored positions are unavailable.
}
}
}
}
キーポイント:
.translationが limitations に現れると位置追跡は利用不可で向き追跡のみ- このコールバックで配置済み仮想コンテンツを再配置するか、より明るい環境への移動を促せる
- システムレベルでは既に向き追跡に自動降级——完全に追跡が失われることはない
Hand Tracking 予測
HandTrackingProvider は display rate でデータを出力。Compositor Services レンダリングシーンで手の位置を事前予測する新 API も追加(12:51):
// Hands prediction
func submitFrame(_ frame: LayerRenderer.Frame) {
...
guard let drawable = frame.queryDrawable() else { return }
// Get the trackable anchor time to target.
let trackableAnchorTime = drawable.frameTiming.trackableAnchorTime
// Convert the timestamp into units of seconds.
let anchorPredictionTime = LayerRenderer.Clock.Instant.epoch.duration(to:
trackableAnchorTime).timeInterval
// Predict hand anchors for the time that provides best content registration.
let (leftHand, rightHand) = handTracking.handAnchors(at: anchorPredictionTime)
...
}
キーポイント:
trackableAnchorTimeは visionOS 2.0 の新タイムスタンプで、最適なコンテンツ整合時刻を表す- 秒に変換して
handAnchors(at:)に渡すと ARKit が前方予測 - 予測結果は遅延が低いが精度はやや犠牲——手に密着したシーン向け
- 精度重視で遅延に鈍感(ジェスチャー検出、描画)なら display-rate の非同期更新が適切
重要ポイント
-
部屋ベースの体験切り替え:RoomTrackingProvider の
isCurrentRoomとcontains(_:)で各部屋に異なる仮想コンテンツをカスタマイズ。価値がある理由:ユーザーは「部屋が変わると見えるものも変わる」体験を直感的に期待。座標による手動分区より信頼性が高い。始め方:Full Space で RoomTrackingProvider を有効化し、anchorUpdates を監視、切り替え時にシーンコンテンツを交換。 -
実物体への仮想情報オーバーレイ:Object Tracking で産業機器、教材、ボードゲーム部品に 3D ラベルやアニメーションを重ねる。価値がある理由:教育、修理、博物館シナリオは「実物を見ながら解説」のインタラクションが自然。visionOS 上でこの類の app はまだ少ない。始め方:CreateML で ReferenceObject を訓練し ObjectTrackingProvider で実行。ObjectAnchor の boundingBox でオーバーレイ位置を決定。
-
暗所での適切な降级:
worldTrackingLimitationsを監視し、位置追跡喪失時に仮想コンテンツをアンカーモードから視点追従モードへ自動切替。価値がある理由:ユーザーは常に明るい環境にいるわけではない。降级なしではコンテンツが漂移または消失。始め方:SwiftUI ビューで.onChange(of: worldTrackingLimitations)により.translation制限を検出し、コンテンツ再配置をトリガー。 -
低遅延の手インタラクション:手に密着したシーン(仮想物体の掴みなど)ではデフォルトの非同期更新ではなく手予測 API を使用。価値がある理由:非同期 HandAnchor には固有の遅延があり、手が速いと仮想物体が「手についてこない」。予測でギャップを縮小。始め方:Compositor Services レンダーループで
drawable.frameTiming.trackableAnchorTimeから目標時刻を取得し、handAnchors(at:)で予測結果を取得。
関連セッション
- Explore object tracking for visionOS — CreateML で ReferenceObject を生成し物体追跡モデルを訓練する詳細ガイド
- Dive deep into volumes and immersive spaces — visionOS における Volume と Immersive Space のカスタマイズを深掘り
- Create custom environments for your immersive apps in visionOS — 没入型 app 向けカスタム環境の視覚とパフォーマンスのベストプラクティス
- Build a spatial drawing app with RealityKit — RealityKit で空間描画 app を構築し、hand tracking の実践的用法を示す
コメント
GitHub Issues · utterances