
-
近くにいるユーザーとvisionOSの体験を共有
同じ室内でVision Proを装着している複数のユーザーが体験を共有できるようにする方法を学びます。SharePlayを統合してアプリでARKitを利用する方法、FaceTimeに参加している近くにいるユーザーがウインドウを共有するための新しいフローの導入方法、シームレスなコラボレーションのための新しいAPIを紹介します。コラボレーション機能を活用し、ほかの人に簡単に見つけてもらい、同じ空間で共同作業するためのベストプラクティスを紹介します。
関連する章
- 0:00 - イントロダクション
- 0:56 - 近くの人との体験共有の詳細
- 4:21 - 近くの人と共有できるアクティビティの構築
- 5:35 - 共有メニューからの共有の許可
- 9:15 - 近くにいる参加者の体験の向上
- 10:37 - ユーザーの相対位置へのコンテンツの配置
- 13:20 - 共有されたメディア再生の調整
- 15:38 - 複数のウインドウのサポート
- 16:50 - アンカーされたコンテンツの共有
リソース
- AVPlaybackCoordinator
- Building a guessing game for visionOS
- Configure your visionOS app for sharing with people nearby
- groupActivityAssociation(_:)
- init(originFromAnchorTransform:sharedWithNearbyParticipants:)
- worldAnchorSharingAvailability
関連ビデオ
WWDC25
WWDC24
WWDC23
WWDC21
-
このビデオを検索
こんにちは visionOS FaceTimeチームの エンジニア Connorです 本日は 新しい機能について紹介します この機能により 共有とコラボレーションが かつてないほど強力になります visionOS 26では アプリや体験を 同じ空間にいる 近くのユーザーと共有できます これにより Vision Proで お気に入りのアプリを使って 周囲のユーザーと一緒に映像や音楽の視聴や 共同作業ができるようになります このビデオでは 近くにいるユーザーと 共有して使用することを 想定したアプリの 設計と構築の方法を学びます まず 機能の概要を説明します 次に紹介するのは SharePlayを使用して 同じ空間にいる全員に提供できる インタラクティブな体験を構築する方法です 最後に 共有コンテンツを ARKitと共有ワールドアンカーを使って 現在の物理空間に固定する方法を解説します まず visionOS 26による 近くにいる ユーザーとの共有の仕組みを説明します これは まったく新しい アプリの共有方法です これまで以上に直感的で 機能を見つけるのも簡単です すべてのウインドウには ウインドウバーの右側にボタンがあります タップすると 共有メニューが開きます そこで 近くにいるユーザーの リストから選択して 簡単に共有を開始できます ユーザーが共有を開始すると そのユーザーが部屋に配置した位置で ウインドウが全員に表示されます ウインドウバーは緑色に変わり ウインドウがその場にいる全員に 共有されていることを示します この体験ではコンテキストが共有されます これにより 同じ空間での共有体験は まるで魔法のようなものになります 共有ウインドウは どのユーザーから見ても 同じ場所に表示されるため アプリについて話し合ったり 場所を 指し示したり アプリを操作したりなど 実際に部屋の中にあるように扱えます
このシステムでは 全ユーザーにとって アプリが表示される場所も サイズも同じです
共有ウインドウは 最初に表示された後は 誰でも動かすことができ その移動は全員が見られ ウインドウは 自然にグループ全体の方を向きます
アプリウインドウのサイズ変更の共有や 共有環境へのウインドウの固定もできます 誰かがDigital Crownを長押しして 再センタリングすると アプリは そこにいる全員にとって 適切な場所に再配置されます 誰かがウインドウ上の点を指差したり ウインドウの場所に手をかざしたりすると コンテンツはフェードして その人の手が見える状態を維持します
この共有コンテキストは 同じ部屋にいる ユーザーだけのものではありません 近くにいるユーザーとの共有の 最も優れた機能の1つは FaceTimeとの高度な統合です アプリを近くにいるユーザーと 共有している時 FaceTimeを起動すると 招待したり 気軽に参加したり 共同作業したりできますが リモートユーザーも参加可能です ユーザーがvisionOSで参加すると スペースに空間Personaとして表示されます 空間Personaは まったく新しいレベルの存在感を実現します 全員が本当に同じ空間にいるかのように 感じることができます
ユーザーが空間Personaとして参加すると システムは最適な場所を見つけ 近くのユーザーと並べて配置します
システムが決定する 空間Personaの配置場所は 共有されるウインドウの種類によって 異なります ボリュメトリックウインドウの共有中に 参加した場合 ボリュームの周囲の隙間を埋めるように Personaを配置することで 近くにいる参加者とリモート参加者の 両方にとって理想的なレイアウトになります FaceTimeをサポートする 他のプラットフォーム 例えば iOSやmacOSなどからも参加できます
参加すると 共有ウインドウの横に ビデオが表示されるため アプリを操作しながら 他のユーザーと快適に会話できます デフォルトでは 共有ウインドウは 開始時点では閲覧専用です そのアプリを所有していない ユーザーとも共有でき その後もアプリの導入は不要です ただし 同じ空間にいるユーザーが共有できる インタラクティブな体験を利用するには SharePlayの導入が必要です 複数のAppleプラットフォーム間での FaceTimeの連携に SharePlayは必須です SharePlayアプリはリアルタイムの インタラクションをサポートし 映画や音楽の視聴、 ゲームプレイ、共同作業など 様々なことを一緒に楽しめるようにします visionOS上の既存のSharePlayアプリは 近くにいるユーザーと共有できます 設定の変更は必要ありません そして SharePlayの エキサイティングな新機能を使うと 同じ空間にいるユーザー間での共有向けに アプリを設計して強化できます
SharePlay初心者の方には まず 「Build custom experiences with Group Activities」と 「Build spatial SharePlay experiences」を 見ることをおすすめします 以降は これらのビデオで紹介されている 概念を前提とした発展的な内容です このセクションで取り上げるトピックは 近くにいるユーザー間で共有される 優れた体験を構築する上で役立ちます 最初に SharePlayアクティビティを 公開することの重要性について説明します アクティビティを 新しい共有メニューに 公開すると 簡単に共有を開始できます 次に 近くにいる参加者を確認することで 同じ空間にいるユーザーの体験を 向上させる方法について説明します また 参加者のポーズを使ってコンテンツを ユーザーからの相対位置に配置する方法と AVPlayerを使用して 近くにいるユーザーと共有される ビデオとオーディオを正確に同期させる 共有メディアの再生方法の例を紹介します 最後に アプリに 複数のウインドウがある場合について SharePlayに関連付けるウインドウを 選択する方法を説明します まず 最初に行う必要があることの1つは SharePlayアクティビティを 共有メニューで利用可能にすることです visionOS 26に 新しい共有メニューが導入され アプリの共有が これまで以上に簡単になりました そのメリットを最大限に活用するには SwiftUIまたはUIKit APIを使用して GroupActivityを共有メニューに 公開する必要があります これにより ユーザーが共有ボタンをタップすれば そのGroupActivityを有効化して SharePlayを開始できるようになります ボリュメトリックウインドウの場合 共有メニューは アプリがアクティビティを 公開している場合のみ使用できます 例えば 友人と直接会った時に ボードゲームで遊べるような SharePlay体験を作成するとします
まず ボードゲームアプリ用のシンプルな GroupActivityを作成します 名称はBoardGameActivityです GroupActivitiesは SharePlayを 強化するフレームワークであり GroupActivityの定義は 共有体験を作成するための最初の手順です また ゲームのメインシーンを設定するため ボリュメトリックのWindowGroupで BoardGameViewを指定します SwiftUIアプリであるため 共有メニューに BoardGameActivityを公開するには ビューの階層に ShareLinkを追加する必要があります BoardGameActivityを渡すのは それが開始すべき対象だからであり 非表示にしたのは アプリのUIに影響を与えないためです 公開したアクティビティが 共有メニューから共有されると 自動的に有効化され GroupSessionが作成されます この仕組みは GroupActivityでactivate()メソッドを 手動で呼び出す場合と同様です
自動的に作成されたGroupSessionを 取得するには BoardGameActivityのセッションを 監視対象にします 次に 実際にSharePlayを開始するには 作成したセッションを構成して参加します
これで ユーザーは共有メニューから直接 アプリの共有を開始できます ウインドウ表示されるアプリと ボリュメトリックアプリの 両方で利用できますが 共有体験でイマーシブ空間を使用する場合は 共有メニューを 常時アクセスできる状態に 維持するために考慮すべき 追加の事項があります 例えば ウインドウ表示されるボードゲームを 部屋の床に置かれたフルサイズの テーブル上のボードゲームに変換し リアル感を高めるために テーマに沿った 3Dオブジェクトを周囲に配置する場合 イマーシブ空間に オブジェクトを配置する必要があります ここで問題となるのは アプリを共有するためのウインドウバーが イマーシブ空間にないことです これを解決するには 独自のボタンを作成し ウインドウやボリュームを使わずに ユーザーが共有を開始できるようにします ユーザーがそのボタンを押すと アプリによってBoardGameActivityの activateメソッドが呼び出されます アクティビティでactivateを呼び出す visionOS 26の新機能によって FaceTime以外でも 共有メニューが自動的に表示されます この機能は ウインドウとイマーシブ空間の どちらでも利用できます 近くにいるユーザーを選択するか 新規のFaceTimeセッションを作成すると アプリから直接共有を開始できます
先ほどの問題の さらに優れた解決方法は 非イマーシブモードの提供を 継続することです
この方法では 非イマーシブウインドウの 共有メニューから共有を開始し 全員が参加したら イマーシブモードに移行します
従来と同様に 実際にSharePlayを開始するには GroupSessionに参加する必要があります 基本事項ですが セッションから systemCoordinatorを取得して supportsGroupImmersiveSpaceを trueに設定する必要もあります イマーシブ空間が全員に同じ場所で 共有されるようにするためです アプリを共有できることが確認できたら 同じ空間にいるユーザーの体験を 向上させ カスタマイズするための 最適な方法の検討に進むことができます この検討では 新しいSharePlay APIを使用して 近くにいる参加者を明示的に確認します これは近くで体験を共有しているユーザーが FaceTimeを開始する場合 特に重要です このボードゲームアプリでは 同じ空間にいる人が FaceTimeから 参加する人と対戦できることが目的です そのために 物理的に一緒にいる参加者を確認し 近くの参加者とチームを組むように 積極的に提案します
これを行うには どの参加者が近くにいて どの参加者がリモートか 把握する必要があります
まず 先ほど参加した GroupSessionから始めます セッションの参加者に関する情報を 取得するには GroupSessionのアクティブな参加者の パブリッシャーを監視対象にします その参加者の状態から 新しいisNearbyWithLocalParticipant プロパティを確認します このプロパティの値は 参加者が 私の近くにいる場合trueになります このチェック対象からは localParticipantを除外します どの参加者が近くにいるかのみが 確認すべき事項であるためです
以上によって 近くにいる参加者が同じチームになり リモートの参加者と対戦できます 同じ空間にいるユーザーに 優れた体験を提供するには 近くにいるユーザーの アプリに対する 相対位置も考慮する必要があります これは 参加者の横や対面の位置に コンテンツを配置する場合に重要です 新しいSharePlay APIは 共有開始時の 各ユーザーの正確な位置を通知します 例をお見せしましょう ここまでは 近くにいるユーザーの各々が アプリに対面した状態で アプリを共有していると想定していました 実際には アプリの共有時に各ユーザーが 空間内のどこにいるかは不明です アプリは特定の位置で共有されるため 共有開始時に 各ユーザーに合わせて アプリが自動的に移動することはありません これは特に イマーシブ空間のアプリで 留意すべき重要な事項です コンテンツを イマーシブ空間の起点ではなく 参加者の近くに配置すべき 場合があるためです この例のイマーシブな ボードゲームアプリで 近くにいる ユーザーにスコアカードを表示する場合
まず イマーシブ空間のシーンに対する 近くにいる各参加者の相対位置を 把握する必要があります この位置情報は ParticipantStateの 新しいPoseプロパティから取得できます
先ほどと同様に 参加済みのグループセッションから始めます localParticipantに関する情報を 取得するには セッションのsystemCoordinatorに アクセスして systemCoordinatorで localParticipantStateの 非同期シーケンスを監視対象にします localParticipantStateを取得したら その状態の 新しいposeプロパティを 参照できます これで ローカルの参加者の ImmersiveSpaceシーンに対する 相対位置がわかります
poseプロパティは参加者の位置を リアルタイムでは追跡しませんが 共有の開始時や ユーザーがDigital Crownを長押しして 再センタリングが行われた時など 重要なイベントの後に更新されます ローカル参加者のポーズが把握できたら 各参加者に対する 相対的なスコアカードの配置場所を計算し 各参加者の横に配置できます
参加者の実際のポーズに加えて 席ポーズを取得できます これは アプリの位置を起点とする 固定的な物理的位置です 席ポーズと 空間テンプレートによる 座席配置のカスタマイズについては 「Customize spatial Persona templates in SharePlay」で詳細を確認してください このビデオで説明している方法を使うと 席ポーズを読み込んで より高度な機能をアプリで実現できます 具体的には テーブルを囲む実際の席に 移動するようユーザーに促すことができます これにより アプリのコンテンツを 立って楽しむのに最適な場所もわかります 既にアプリで席ポーズを使用しており ユーザーがすでにいる位置に コンテンツを配置したい場合 参加者ポーズへの切り替えを検討しましょう
共有ビデオや共有オーディオを使用する 体験のために visionOS 26では AVPlayerがアップグレードされ 同じ空間にいるユーザー間で 再生を調整できるようになりました 同じ空間にいるユーザーが共有メディアを 使用する場合 独自の課題があります これは ユーザーが物理的に 互いの近くにいることに起因します 近くにいるユーザーがメディアを共有すると 他の参加者のデバイスから 音声が聞こえる場合があります そうした状況では 音声の わずかな遅延も目立ち 全参加者の体験が損なわれます そのため 全ユーザーに対し 映像や音声が同様に遅延なく 再生されることが重要です visionOS 26に導入された AVPlayerと AVPlaybackCoordinatorの新機能では 同じ空間にいるユーザーのオーディオと ビデオの再生を 正確に同期できます
この機能のデモとして ボードゲームアプリに 新しい説明ビデオの機能を追加します ユーザーはいつでも共有ビデオを見て ゲームのプレイ方法を確認できます このビデオは 全ユーザーが遅延なく 同時に再生できるようにする必要があります ビデオの再生が終了したら プレーヤーはゲームに戻り 確認した内容に従ってプレイできます
このアプリで AVPlaybackCoordinatorを作成し GroupSessionにおいて設定します これにより 同じ空間にいる全ユーザーに対して ビデオの再生が正確に同期されることを 担保できます つまり このアプリの全ユーザーが 説明ビデオの再生を エコーや遅延なしで 同時に視聴できるようになります
SharePlayにおける AVPlaybackCoordinatorの設定方法は 「Coordinate media experiences with Group Activities」をご覧ください visionOS向けのメディアアプリを 初めて構築する場合は 「Create a great spatial playback experience」のビデオもご覧ください アプリのオーディオとビデオが 完全に同期されるようになりました しかし 説明ビデオウインドウを追加したことで 新しい問題が生じたため 解決する必要があります このアプリでは 同時に複数の ウインドウグループが開かれています Board Game Volumetricウインドウと Instructional Videoウインドウです この状態をサポートするには 両ウインドウが開いている間 どちらを 共有するかより明確にする必要があります visionOS 26の新しいSharePlay APIでは ビューモディファイアを使用して 特定の時点でSharePlayに関連付ける ウインドウグループを正確に指定できます 複数のウインドウを使用するアプリを かつてなく高度に制御できるようになります
先ほどのボードゲームアプリのコードには WindowGroupがあります 新しい説明ビデオを追加するために ビデオビューをホストする 2つ目のWindowGroupを作成します 次に 新しい.groupActivityAssociation ビューモディファイアを そのWindowGroupのビューに追加します
.groupActivityAssociationに primaryを渡すことで このウインドウは 開かれている間は共有されるよう 設定していることをシステムに伝えられます
これで このボードゲームアプリは随時 完全に同期された共有ビデオに切り替えて 全員がプレイ方法を理解できたら ゲームに戻れるようになりました
皆さんがこれらの機能強化を どのように活用して 素晴らしいソーシャル体験を生み出すか とても楽しみです 今こそ SharePlayを導入する 絶好の機会と言えますが 近くにいるユーザー間の共有をサポートする 新しいAPIを備えたフレームワークは GroupActivitiesだけではありません visionOS 26ではARKitもアップデートされ 共有ワールドアンカーを使用して 同じ物理的な場所で 共有コンテンツを アンカーできるようになりました 先に進む前に イマーシブ空間の主な概念と 通常のワールドアンカーについて おさらいしておきましょう イマーシブ空間をアプリで使用すると ユーザーの周りの空間のどこにでも コンテンツを自由に配置できます これは ユーザーの周囲に コンテンツを提示する上で便利ですが イマーシブ空間は 物理的に同じ場所に 常に留まるとは限りません あるユーザーが移動し Digital Crownを 長押しして再センタリングすると イマーシブ空間全体が調整されます これは多くの場合問題になりませんが コンテンツを一定期間にわたり 物理空間に固定して表示したい場合 好ましくありません この問題を解決するのが ARKitのワールドアンカーです ワールドアンカーを使用すると アプリのコンテンツを ユーザーの空間内の物理的位置に 固定して配置できます このコンテンツはシステムにより 時間の経過に関わらず 常に正確に同じ場所に固定されます Digital Crown長押しの 再センタリングも適用されません
例えば 実世界にバーチャルの家具を配置し フロアプランを検討したり 新しいデザインを試したりできる アプリを作成するとします このようなアプリで 重視されるのは 配置した家具が 常に同じ物理的位置にあり 時間が経っても勝手に移動しないことです このアプリを構築する上で必要になるのは イマーシブ空間の起点に対する 特定の相対的位置にコンテンツを配置し ワールドアンカーを使用して その位置に固定できる機能です まず ARKitSessionと WorldTrackingProviderを設定します 次に セッションで WorldTrackingProviderを実行します 家具アプリ用の 新しいアンカーを追加する場合 イマーシブ空間内の家具に対応する 特定のtransformで WorldAnchorを作成し WorldTrackingProviderに追加します 最後に WorldTrackingProviderの anchorUpdatesシーケンスで updateをリッスンします このupdateは 新しいアンカーが 正常に追加された時に呼び出されます これで 家具のモデルを アンカーして配置できるようになりました
同じ物理空間にいるユーザーが アプリを共有できるようになったことで ワールドアンカーはこれまで以上に 重要になっています 近くにいるユーザーとの共有では 部屋は共有コンテキストの一部です ワールドアンカーを使用することで 空間を共有コンテキストとして 活用できるようになります アプリの共有時に 共有コンテンツを 特定の物理的な場所に配置するには 新しいAPIにより 近くにいるユーザーとの共有の対象として アンカーをマークする必要があります このAPIを使用すると SharePlayセッションの間に 近くにいる参加者と自動的に共有される ワールドアンカーをアプリが作成します このアンカーは 近くにいる参加者との間でのみ共有されます 共有アンカーを作成できるのは SharePlayがアクティブな時のみで 通常のワールドアンカーとは異なり 共有の終了後は維持されません
先ほどの家具アプリに 共有ワールドアンカーを導入しましょう ユーザーが部屋に家具を追加すると 近くにいる参加者全員に その家具が表示されるようにします これにより 参加者全員が部屋のデザインを 一緒に考えているような気分になります 最初に 共有ワールドアンカーが 利用可能であることを確認してから 作成を開始します newWorldAnchorSharingAvailabilityを WorldTrackingProviderで監視対象にします この値がavailableだと 近くにいる ユーザーがアプリを共有中ということであり 共有ワールドアンカーを作成できます
これ以降 共有ワールドアンカーの作成方法は 通常のワールドアンカーの場合と 非常に似ています 家具を追加するユーザーのために WorldAnchorの作成時に sharedWithNearbyParticipantsに trueを渡します 次に 近くにいるすべての参加者の WorldTrackingProvidersで anchorUpdatesシーケンスから 新しい共有アンカーを受け取ります 全参加者のデバイスで 識別子はまったく同じになります この識別子を読み込んで同期することで 各デバイスのアンカーにどのコンテンツを 関連付けるか アプリが把握できます
共有ワールドアンカーは 独自のネットワークレイヤーを SharePlayの外部で使用することで ビジネスアプリでも使用できます 近くにいるユーザーと共有できる 空間ビジネスアプリの構築方法については 「Explore enhancements to your spatial business app」のビデオで 詳細をご確認ください
近くにいるユーザーと コンテンツを共有することのメリットは 同じ空間で一緒の体験を楽しめることです また 共有ワールドアンカーを使用すれば ユーザーが一緒にいる空間を 最大限に活用して 素晴らしい体験を提供できます
このビデオの次のステップとして SharePlayを使用したインタラクティブな 共有体験を ご自身のアプリでサポートする 最適な方法を検討しましょう 複数のユーザーが アプリコンテンツを 一緒に楽しめる方法を考えます SharePlay導入後は 新しい共有メニューの サポートを追加して ご自身のアプリで 共有を簡単に開始できるようにしましょう アプリの共有体験を システムUIから 直接見つけられるようになるため 共有体験を強力にアピールできます あらゆる対応プラットフォームで 近くにいるユーザーと リモートユーザーの両方に最適な体験を 設計する方法を検討しましょう 共有の対象が 近くとリモートの 両方の参加者であることを意識してください 同じ部屋にいるユーザーと 世界中のユーザーを アプリでつなげられることで生まれる 無限の可能性を活かす方法を考えましょう 最後に 物理的な空間をフルに活用した 体験を構築しましょう ワールドアンカーにより ユーザーの室内で バーチャルコンテンツの実在感と インタラクティブ性を強化できます これらすべてを組み合わせれば 可能性は無限大になります 物理的な壁を使用して 共同の ホワイトボードセッションを実施したり リビングで イマーシブなゲームをプレイしたり 自室を映画館に変えて 友人とムービーナイトを楽しんだりできます 近くにいるユーザーと体験を共有する機能は 周りの人々とつながり協働するための 斬新でパワフルな方法をもたらします 空間を共有する人々が 互いのつながりを より強く感じられるようにする 素晴らしい体験を創造しましょう
-
-
6:21 - Expose an activity with GroupActivities and SwiftUI
// Expose an activity with GroupActivities and SwiftUI import SwiftUI import GroupActivities struct BoardGameActivity: GroupActivity, Transferable { var metadata: GroupActivityMetadata = { var metadata = GroupActivityMetadata() metadata.title = "Play Together" return metadata }() } struct BoardGameApp: App { var body: some Scene { WindowGroup { BoardGameView() ShareLink(item: BoardGameActivity(), preview: SharePreview("Play Together")) .hidden() } .windowStyle(.volumetric) } } struct BoardGameView: View { var body: some View { // Board game content } }
-
7:14 - Join a GroupSession with GroupActivities
// Join a GroupSession with GroupActivities func observeSessions() async { // Sessions are created automatically when the activity is activated for await session in BoardGameActivity.sessions() { // Additional configuration and setup // Join SharePlay session.join() } }
-
8:57 - Join and configure a GroupSession with GroupActivities
// Join a GroupSession with GroupActivities func observeSessions() async { // Sessions are created automatically when the activity is activated for await session in BoardGameActivity.sessions() { // Additional configuration and setup guard let systemCoordinator = await session.systemCoordinator else { continue } systemCoordinator.configuration.supportsGroupImmersiveSpace = true // Join SharePlay session.join() } }
-
9:59 - Check for nearby participants with GroupActivities
// Check for nearby participants with GroupActivities func observeParticipants(session: GroupSession<BoardGameActivity>) async { for await activeParticipants in session.$activeParticipants.values { let nearbyParticipants = activeParticipants.filter { $0.isNearbyWithLocalParticipant && $0 != session.localParticipant } } }
-
11:42 - Observe local participant pose with GroupActivities
// Observe local participant pose with GroupActivities func observeLocalParticipantState(session: GroupSession<BoardGameActivity>) async { guard let systemCoordinator = await session.systemCoordinator else { return } for await localParticipantState in systemCoordinator.localParticipantStates { let localParticipantPose = localParticipantState.pose // Place presented content relative to the local participant pose } }
-
15:54 - Associate a specific window with GroupActivities and SwiftUI
// Associate a specific window with GroupActivities and SwiftUI import SwiftUI import GroupActivities struct BoardGameApp: App { var body: some Scene { WindowGroup { BoardGameView() ShareLink(item: BoardGameActivity(), preview: SharePreview("Play Together")) .hidden() } .windowStyle(.volumetric) WindowGroup(id: "InstructionalVideo") { InstructionalVideoView() .groupActivityAssociation(.primary("InstructionalVideo")) } } } struct BoardGameView: View { var body: some View { // Board game content } } struct InstructionalVideoView: View { var body: some View { // Video content } }
-
18:27 - Create a world anchor with ARKit
// Create a world anchor with ARKit import ARKit class AnchorController { func setUp(session: ARKitSession, provider: WorldTrackingProvider) async throws { try await session.run([provider]) } func createAnchor(at transform: simd_float4x4, provider: WorldTrackingProvider) async throws { let anchor = WorldAnchor(originFromAnchorTransform: transform) try await provider.addAnchor(anchor) } func observeWorldTracking(provider: WorldTrackingProvider) async { for await update in provider.anchorUpdates { switch update.event { case .added, .updated, .removed: // Add, update, or remove furniture break } } } }
-
20:02 - Observe sharing availability with ARKit
// Observe sharing availability with ARKit func observeSharingAvailability(provider: WorldTrackingProvider) async { for await sharingAvailability in provider.worldAnchorSharingAvailability { if sharingAvailability == .available { // Store availability to check when creating a new shared world anchor } } }
-
20:24 - Create a shared world anchor with ARKit
// Create a shared world anchor with ARKit import ARKit class SharedAnchorController { func setUp(session: ARKitSession, provider: WorldTrackingProvider) async throws { try await session.run([provider]) } func createAnchor(at transform: simd_float4x4, provider: WorldTrackingProvider) async throws { let anchor = WorldAnchor(originFromAnchorTransform: transform, sharedWithNearbyParticipants: true) try await provider.addAnchor(anchor) } func observeWorldTracking(provider: WorldTrackingProvider) async { for await update in provider.anchorUpdates { switch update.event { case .added, .updated, .removed: // Add, update, or remove furniture. Updates with shared anchors from others! let anchorIdentifier = update.anchor.id } } } }
-