ストリーミングはほとんどのブラウザと
Developerアプリで視聴できます。
-
RealityKitでAppを構築する
簡単に学べるAPIを使用してゲームを開発し、RealityKitの機能を実践的に理解していきましょう。このセッションでは、アセットのロード、シーンの構築、アニメーションの適用、ゲームインプットの処理において推奨されるアプローチを紹介します。エンティティとコンポーネントにはRealityKitの強力な要素が表れており、同時にカスタマイズのための柔軟性も確保されています。組み込みのネットワーキング機能を活用し、ゲームで臨場感あふれるマルチプレイヤー体験を実現する方法の詳細についてご確認ください。
リソース
関連ビデオ
WWDC19
-
ダウンロード
(音楽)
(拍手) こんにちは
RealityKitチーム エンジニアのロスです
今回は過去に開かれたセッションの フォローアップを目的としています アプリケーション構築や フレームワークの活用など RealityKitの応用を お話しします RealityKitを 簡単に説明すると― ARアプリケーションのための フレームワークです シンプルで直感的な開発を 可能としました ARのために作成され 仮想物体とリアルワールドを融合します Swift APIにより 簡素化されました やってみましょう
今から作るのは 神経衰弱ゲームのアプリケーションです カードをタップすると イメージが出現 同じカードを選ぶと 2枚とも消えます 失敗すると裏返り 再び選べるようになります ゲームを通して RealityKitを説明します ゲームは4段階で作成します まずプロトタイプを作り ARでインタラクションを 行えるようにします
次にアセットを加えるなど 精度を上げ Entity Component Systemを使用 最後にRealityKitの ネットワークサポートを使います
プロトタイプから始めます RealityKitでは 4つのオブジェクトを使用します まずARビュー シーン アンカー そしてエンティティです
ARビューはARの世界への窓であり ビュー階層へ入ることができます
仮想コンテンツを 支えるのがシーン
アンカーがリアルワールドへの 仮想コンテンツの配置を可能にします アンカーをシーンに追加すると 自動的にリアルワールドに配置されます アンカーを使い ゲームボードを配置しましょう エンティティによって 仮想コンテンツが表示されます 今回の場合は ゲームのカードですね カードと同数の エンティティが必要です
アプリケーションに必要な 要素の説明は以上です アンカーの説明に移ります
RealityKitのアンカーは ARkit上で構築されます まずAnchorEntityを作り アンカータイプを突き止め シーンに加えます
AnchorEntityが ターゲットをトラッキングし 仮想コンテンツを リアルワールドに配置
ARKitの全アンカータイプに 対応しています プレーン フェイス イメージ オブジェクトやボディなどです
ボードの配置に 必要なアンカーは1つ カードを並べるので 20センチ四方の水平面が必要ですね
アンカーによって ゲームボードが表示されるように コードを書きましょう View Controllerです ARビューを配置 アンカー探しと仮想コンテンツ作成は viewDidLoadで行います
AnchorEntityを作成し イニシャライザを活用することで アンカータイプを特定します 最低限必要な広さを 指定することも可能です RealityKitは メートル法に基づくので 20センチの場合 0.2と入力します あとはシーンにアンカーを加え 条件に合う広さを検知すると アンカーのコンテンツが ARに表示されます
仮想コンテンツを加えましょう まずモデルをロードします RealityKitは USDZのアセットに対応 非同期ロードも可能ですが 今回は同期ロードを行います
USDZなどをロードすると 自動的にエンティティ階層や メッシュやマテリアル アニメーションもインポートされます
カードのアセットをロードします
ロードするには アセット名のメソッドがいります Appバンドルにあれば 拡張子の特定は不要です ロード可能な状態だと エンティティを自動的に作成します 8種のカードのモデルを ロード中です
今回は16枚のカードが必要です 異なるイメージのカードが8枚 そして各タイプを2枚ずつ 8ペア作成します それぞれ対となるカードを どう作るのか? メソッドを 呼び出すこともできますが すべてのカードに対して 設定が必要になります もっと簡単に クローンを作成できます cloneメソッドを呼び出し オリジナルのクローンを 作成します オリジナルのアセットが 参照されます 子エンティティも 再帰的にクローンされます 複雑なシーンを構成する時に 役立つでしょう クローンはインスタンスではないので ご注意ください 例えば オリジナルの子を削除しても 作成済みのクローンに 変更は反映されません クローンでペアを作成します
それぞれインスタンスの クローンを2つ作成し 別々に配列します オリジナルのテンプレートを 使うことも可能ですが あとの手間を考え テンプレートは残してください
ゲームボードに カードを配置しましょう アンカーを中心に カードは4×4に配置します カードをアンカーに加えれば ARCに表示されます
そのためにindexとarrayを使い 位置を計算します 各カードを追加する際 アンカーと相対的に配置されます
以上で配置とレンダリングの 準備ができました それでは インタラクションを加えましょう
タップするとカードがめくれるよう 設定するために デバイス上のタップを ARの世界に変換します ヒットテストの 解決策を紹介します デバイスをタップして2Dポイントを 仮想シーンの光線に変えます 光線がシーンに投影され オブジェクトと交差します エンティティが返され タップしたオブジェクトが分かります まずエンティティは カメラに最も近いものを返し そして光線と交差する あらゆるエンティティを返します
これをゲームに移行します TapGestureRecognizerの 応答のメソッドは タップした位置を エンティティに送ること デバイスに近い エンティティを使うからです タップ位置の下に エンティティがあれば返し インタラクションを実行します もう1つやることがあります
ヒットテストには コリジョンシェイプが必要です コリジョンとは ジオメトリを単純化したもの 特定しやすく 効率的な物理判定を可能にします コリジョンシェイプなしでは ヒットテストは行えません
先ほどお見せしたのと 同じコードです
ここにコリジョンシェイプの メソッドを加えます 自動的に コリジョンシェイプを作成します 目に見える境界を使用します クローン作成と同様に 再帰的であり 子のコリジョンシェイプも 作成できるのです なおコリジョンシェイプは― エンティティのクローンを作成する際に 自動的にコピーされるデータの1つです
では カードをタップした時の アニメーションを追加します 対応しているのは2種類 1つはTransform Animation 移動や回転をさせたり 縮小や拡大を加えられます
もう1つはAsset Animation ベイクされたアニメーションを 再生します いずれもCompletion Handlerが 使用可能です 今回はベイクされていないため Transform Animationを使用します
アニメーションの 再生速度などを調整できます リニアは加速や減速もできますが 一定速度で再生します イーズインによって 速度を上げることも
イーズアウトで 速度を下げることもできます
両方を組み合わせれば― 前半の速度を上げ 後半の速度を下げることができます より細かく カスタマイズすることも可能です アニメーションを作りましょう
カードのトランスフォームを コピーします これにより現在のスケールと エンティティの変換を保持できます
クォータニオンでトランスフォームを X軸で180度回転させることによって カードが表を向きます
これで自動で再生されます エンティティの 移動メソッドが使用されます 指定したtiming functionにより エンティティが スムーズに再生されます カードを表に向ける アニメーション作成方法です
一時停止 再生 停止 またアニメーション完了時に 通知を受け取ることができます
カードを裏返すには トランスフォームの 回転値をゼロに戻します トランスフォームの移動により 裏返しになります
ヒットテストで ユーザが選択したカードを検知し アニメーションで裏返します
基本は完成したので 仕上げていきましょう
ロードしたカードのイメージは2Dで 面白みに欠けます 高品質な立体モデルを アプリケーションに加えましょう
先ほどと同じ方法で アセットをロードできます しかしモデルが 精密であればあるほど ロードに時間がかかります ロード中 アプリケーションは ブロックされます 大量にロードすると 大幅に時間が取られる可能性も 改善策はあるでしょうか? 同期ロードか非同期ロードを 選べます メソッドを呼び出すことで 非同期ロードが可能です バックグラウンドで ロードが行われます アプリケーションを 中断することなく ARkitを使い続けられるのです ロードが完了すると 通知されます アセットは 同期ロードしたのと変わりません 複数のロードリクエストも可能です すべてのアセットをロードし終えると 通知されます 非同期ロードのコードを 書きましょう モデルを1つ 非同期ロードします 非同期メソッドは同期型と同じように アセット名を取ります ロードの完了時に通知されるよう リクエストを返します クロージャを使用し 同期メソッドを呼び出します リクエストには 過去に紹介したAPIを使います Introducing Combine and Advances in Foundationをご確認ください 以上が非同期ロードの方法です 個別に設定することも 1つにまとめることもできます
最初のリクエストに 他のを追加し collectに続いて sinkを呼び出します ロードが完了すると クロージャが実行され 配列パラメータのモデルに パッケージされます
これを拡大することもできます 8つのモデルを 1つのリクエストにまとめました ロード後に クロージャが実行されます まとめると 作業が簡素化されるのです
ロードを比較しましょう 左は同期ロード 右が非同期ロードです 同期ロードの場合 終わるまで アプリケーションがブロックされます 非同期アプリケーションは レスポンスがあり カメラの前の世界が 映し出され続けます そのためロード時間は 両者ともほぼ変わりませんが 非同期ロードなら 先にコンテンツが配置されます ただしARとの併用に 適していません
モデルをロードしました しかしカードが裏返しでも モデルが見えてしまいます これでは裏返さずとも カードをのぞきこむだけで どれがペアか 分かってしまいます
解決策は Occlusion Materialです シーンのジオメトリに 適用すると 仮想コンテンツを隠し 背景が透けて見えます シーンにジオメトリを加え オブジェクトの ハイライトを追加しました 上下するに伴い ロボットの一部が隠れ リアルワールドが 透けて見えます 机や壁のような 現実のオブジェクトが 仮想のオブジェクトを遮ります 設定してみましょう
Occlusion Planeを追加します プレーンメッシュを作成したら Occlusion Materialと ModelEntityを作ります モデルと交差しないよう ボードの少し下に配置します あとはアンカーに 追加するだけです
うまく動作していますね 問題を解決できたように 思えますが デバイスを下げると 下の仮想コンテンツが見えます このような角度にも機能する オクルージョンが必要です
ボックスの オクルージョンを使います まずボックスを作成 ボックスを使い ModelEntityを作ります オブジェクトの基点が センターなので ボックスがゲームボードの すぐ下に収まるよう調整します 再度アンカーに加え ボックスを配置します
変化がないように見えますが デバイスを下げても 仮想コンテンツが見えなくなりました Occlusion Boxによって レンダリングを防いでいるのです アプリケーションが 完成しました 非同期ロードを行い オクルージョンジオメトリを 活用しました 続いて 同僚の コートランドの登壇です (拍手)
ありがとう ロス エンジニアのコートランドです プロトタイプ インタラクション アートワークの統合を説明しました 今から話すのは トラッキング方法と マルチプレーヤーの加え方です トラッキングから始めます
オブジェクト構築に使うのは Entity-Component design pattern エンティティは コンポーネントで構成されます コンポーネントはエンティティに加える 動作などを定義します コードの再利用が可能で 柔軟性があります まずはコンポーネントについて
使っているのはModelEntity 一連のコンポーネントが提供され 使い勝手に優れています ModelComponentや CollisionComponent そしてPhysicsComponentは 他のオブジェクトとの インタラクトを可能にします 不要なものがあれば削除したり 必要なものを追加したり エンティティを カスタマイズできるのです カードで試してみましょう
PhysicsComponentは 不要なので削除します カードの状態や ペアのカードがそろったか 判断するために保存が必要です そのため新しいコンポーネントを 作らなければなりません 改めてコンポーネントとは?
コンポーネントは Swift構造体です コンポーネントプロトコルに 準拠します Codableプロトコルも いいでしょう 作ってみます CardComponentを宣言し Codableプロトコルに準拠させます
カードの情報を表す ブール値のrevealedと カードを一致させる 文字列のkindを追加します ロード済みのカードを 使用しましょう PhysicsBodyComponentは physicsBodyの プロパティで削除します nilを代入するだけです
コンポーネントをロードするには インデックス付けされた配列に代入 存在しない場合 エンティティに追加されます
kindのプロパティを変更する際も 同じように代入されますが アクセサが オプショナルバリューを返すことも
コンポーネントの コンフィギュレーションですが 独自のエンティティ作成が可能です 数多くのコンフィギュレーションが 既にそろっていますが 作成することもできます カードを多く使うゲームなので 理想的な候補です オブジェクトの コンパイル時間や静的型付け― 機能をカプセル化する メソッドも加えられます これはカードの ステートや動作など 複数のコンポーネントを 変更する際に便利です エンティティの作成は簡単です まず新しいクラスを用意します
必要な既存のコンポーネントと カスタムコンポーネントを加えます PhysicsBodyComponentで 先ほど行った処理を ここでも行います revealとhideメソッドで 拡張します
独自のエンティティクラスを 作成しました 次にコンポーネントを含めます HasModelと HasCollisionを追加 これによりモデルや CollisionComponentに アクセスできるようになります 最後にカードのプロパティを追加し 非オプショナル型に設定します
ゲッターが CardComponentを取得します デフォルト値を返す場合 Nil Coalescing Operatorを使用 セッターはコンポーネント配列に newValueをコピーします クラスができたので メソッドで拡張します
revealメソッドを含めました まずカードのステートを 更新します アニメーションの途中で タップされないよう即座に行います あとは先ほどカードをめくったのと 同じコードを使うだけです Hideメソッドは逆です revealをfalseに設定します 実際に見てみましょう onTap Handlerに戻ります 今回はカードのエンティティに 結果をキャストします 他のエンティティを 使う人もいるでしょう キャストし カード特有の動作を行わせましょう カードが表示されているか 確認するだけで十分です 表示されていれば隠しますし そうでなければ表示します カプセル化しているので カードの動きの詳細を 気にする必要はありません
カスタムコンポーネントを追加し 重要な変更を行いました 表示されたカードをタップし 裏返すことができます それではゲームを 次のレベルに進めましょう 簡単に追加できるのは何か?
マルチプレーヤーですね
友人とARゲームで遊べたら さらに楽しいでしょう シンプルなカードゲームが 対戦になるのです ただしマルチプレーヤーの ARゲームには いくつか独自の課題があります 誰が見てもオブジェクトが同じ場所に 配置されているようにすること また皆がその場にいるため デバイス間の更新速度を 上げなければなりません RealityKitで 実現が可能になりました collaborative sessionによって マルチプレーヤーの追加に 必要なツールを入手できます このゲームにおける マルチプレーヤーとは? 両プレーヤーは いつでもカードをめくることができ お互い カードを見られます 相手の行動に注意を払えば 有利になるのです めくったカードが分かるよう 白い小さな円を加えました
詳しく説明しましょう 自動でシーンの同期が可能です すべてのデバイスに 変更が反映されます
レバレッジ デバイス検出 マルチピア接続など サーバを維持せずとも 付近のデバイスに 接続しやすくなりました オーナーシップモデルで ピアの調整を可能にし
Wi-Fiが混雑していても 低遅延を実現します
マルチプレーヤーの加え方を 説明します まずホストを指名し ゲームボードを配置します メインメニューで 選択してもらいます やり取りができるように セッションを接続します collaborative sessionで ピアとマップを 共有できるようにします 特定の場所に ゲームボードを置くアンカーを作り ピア間を調整します またカードをめくるなど 変更を行うために オーナーシップを使います ユーザは ホストか参加者を選択します 接続を確立するのに使うのは― Multi-Peer Connectivityフレームワーク 今回は深く掘り下げません 詳細は2014年のCross Platform Nearby Networkingのセッションで MCPeerIDと MCSessionを作ります 暗号化を有効にするのを お忘れなく
ホストがアドバタイズに使うのは MCNearbyServiceAdvertiser 利用可能なセッションを 知らせます MCNearbyServiceBrowserで 参加者がセッションを検索 MCSessionの使用を RealityKitに命令するため マルチピア接続サービスを 作ります MCSessionをカバーすることで シーンを同期します 作成したら 同期サービスプロパティに代入します 2つのデバイスが 接続されました しかしお互いがどこにいるのか 把握できていません ARKit 3に導入された collaborative sessionを活用します 世界をより速く構築し 複数のユーザが 同じ経験を共有できます 共同のマッピングをオンにする方法は あとで説明します 新しいトラッキング構成を 作ります trueに設定された コラボレーションが ARセッションに 実行を指示します 準備が整ったので 同期アンカーを作成します 先ほど作成したのは 20センチ四方の水平面を求める AnchorEntityです 今回は周りを歩けるような 場所が必要です ホストに配置してもらいます そしてARKitがアンカーを 同期するよう設定します その方法は?
onTap Handlerを使います リアルワールドに raycastしましょう ヒットテストと似ていますが 今回はリアルワールドに対して 行われます ゲームボードを置くのに 水平面が必要です
水平面を見つけたら ARアンカーを作成します ARKitのアンカーを ARセッションに追加し ARKitによって位置が調整される アンカーを作成します AnchorEntityを作りましょう ARKitとRealityKitの架け橋です ゲームボードは 先ほどと同じですが 今回はホストが作ります 他の人は自動的に受け取ります ロードしたモデルは 同期していません 先ほどのロードを 覚えていますか? 毎回 行うようにしてください ゲームの準備が整いました
ホストがボードを配置したのを 確認できます 同じ場所に配置されています ホストがカードをめくります 一致しませんでした 参加者側にも反映されています ネットワークは不要です 続いて参加者がめくります ホスト側に反映されていません まずオーナーシップを 説明します オーナーシップは エンティティを変える権利です エンティティを作った1人が オーナーになります 今回の場合はホストですね
オーナーシップを譲渡すれば 他者が変更できます どのエンティティをいつ移すか 決めることができるのです 私たちのゲームを例に 説明しましょう
ホストがカードを作成し 所有します カードは 参加者側に表示されます オーナーが 裏返すなどして変更を加えると 参加者側に反映されます RealityKitは マルチプレーヤー対応 アニメーション化の指示を 同期するだけなので 参加者側がスムーズなのです 参加者がめくります エンティティを所有しないので ピアは変更されません ローカルで変更はできますが オーナーが更新したら上書きされます 変更を加えたいのにできません 参加者がめくる前に戻ります オーナーシップは譲渡可能です 誰でも要求できます 黄色いロボットのオーナーシップを 要求させましょう オーナーシップを ホストに要求します 譲渡するか オーナーが判断します 別のピアが要求するなどした場合 拒否される可能性も デフォルトだとオーナーシップは 参加者に譲渡されます 変更を加えられるようになりました カードをめくると ホスト側に反映されます 方法を簡素化しました
まずオーナーシップを 要求します 既に所有していれば 問題なく要求が認められます 返されると 権利が付与されたか知らされます 付与されたら カードをめくります しかし要求が拒否された場合 別のカードを 選ぶことができます 双方で動作するようになりましたが もう一歩先を目指しましょう カードの表示中 オーナーシップを保持し いかなる要求をも 拒否したいと思います revealメソッドへ戻ります
前回 trueに設定しましたね Codableプロトコルを採用したので 他のピアを自動的に更新します オーナーシップ譲渡モードを マニュアルに設定します これにより 要求は自動的に拒否されます オブジェクトが隠れると 要求を受け付け始めます hideメソッドの一例です revealedをfalseに変更後 譲渡モードを自動承諾へ 要求を受けるよう RealityKitに指示されます ホストはオーナーシップに関して 権利を持ちません ボードを配置し 最初はカードを所有しますが それ以外は他のピアと同じです 一度移されると ホストも要求しなければなりません モードを変えて 変更することは可能です もう1つ特徴があります 2人以上で遊ぶと ボードに混乱が生じます 誰がどのカードを選んだか 分かりづらいのです 透明な円盤を追加しましょう すべてが共有されるので 自分が選んだカードも 共有されます RealityKitはローカル限定の エンティティにも対応 ポーカーのように 隠した情報を示すのに適しています 同期コンポーネントを 削除するか 他のエンティティと同様に 処理します
エンティティの子も 共有されません ツリー全体をローカルにするのに 役立ちます
選択内容を表示するクラスを 作りました 透明な円盤が追加されます revealメソッドに 追加しましょう
エンティティを カードの上に配置します エンティティを 共有したくないので 同期コンポーネントにnilを指定 階層に入るため 子を追加します カードを隠す時は 削除しなければなりません hideメソッドです
他のプロパティを変えたら 子に繰り返します タイプを選択する エンティティを探します 見つけたら親から削除します そしてループから抜け出します
オーナーシップとローカルの エンティティの処理は以上です デバイス間で 正しく動作しています 2つのデバイスを使いましたが コードを追加せず 多くのデバイスに対応できます
おさらいです RealityKitは ARを簡単に作成できます 今日 学んだのは コンテンツの配置 アセットをロードする2つの方法 インタラクション統合 カスタムコンポーネント作成 そしてマルチプレーヤーの追加です RealityKitの知識は 深まったでしょうか 活用されるのを 楽しみにしています 詳細とセッションの映像は ウェブをご確認ください RealityKitや collaborative sessionなどについて 他のセッションでも扱っているので お見逃しなく ラボでもお待ちしております 引き続きお楽しみください (拍手)
-
-
特定のトピックをお探しの場合は、上にトピックを入力すると、関連するトピックにすばやく移動できます。
クエリの送信中にエラーが発生しました。インターネット接続を確認して、もう一度お試しください。