ストリーミングはほとんどのブラウザと
Developerアプリで視聴できます。
-
visionOSにおけるゲームでの入力の詳細
visionOSのゲームで優れた入力をデザインし実装する方法を学ぶセッションです。システムのジェスチャを利用して、プレイヤーとゲームの間のインタラクションをスムーズにする方法を解説します。また、カスタムジェスチャとゲームコントローラをサポートする際のベストプラクティスもご紹介します。
関連する章
- 0:00 - Introduction
- 0:56 - Design around gestures
- 3:28 - System gestures
- 6:14 - Combination gestures
- 7:43 - Custom gestures
- 11:24 - Physical controllers
リソース
- Composing SwiftUI gestures
- Forum: Graphics & Games
- Human Interface Guidelines: Game controls
- Human Interface Guidelines: Gestures
関連ビデオ
WWDC24
WWDC23
WWDC22
WWDC21
-
ダウンロード
こんにちは Technology Evangelism チームのCharlynです 今日はvisionOSでの優れたゲーム入力を 実現する要素について説明します
visionOSで制作できるゲームの種類や ゲームの開発に使うことができる フレームワークには 非常に多くの柔軟性があります
Apple Vision Proでは 視線と手を使用して システム上のアプリやゲームを操作します また 外部の物理的な入力デバイスも サポートされています ジェスチャを中心にデザインされた ゲーム入力は 追加の機器がなくてもプレイヤーがすぐに ゲームを始められる最も簡単な方法です 選択可能な様々な種類の ジェスチャについて見ていきます その後 visionOSでサポートされている 物理的な入力デバイスと それらのサポートを追加する場合の 注意事項について 説明します visionOSのジェスチャでデザインされた入力は 直接的なものと間接的なものに分かれます 直接的なジェスチャでは 直接手を伸ばし バーチャルオブジェクトを操作します 注意点として visionOSの無限のキャンバスでは プレイヤーがオブジェクトを操作するために 腕を大きく動かす必要があるかもしれません 間接的なジェスチャでは オブジェクトを見て タップして選択することで 離れた場所にある オブジェクトを操作します そのため 手を体の近くに 置いておくことができます 間接的な入力では プレイヤーの手の小さな動きを 大きな動作に拡大します 表示領域のはるか遠くに手を伸ばしたり 大きな動作を繰り返したりする場合 間接的な入力のほうが 長時間プレイした場合に疲れにくくなります 例えば これは「Loona」という visionOS向けのパズルゲームですが 間接的な入力によって離れた場所にある それぞれのピースを掴むことができます ピースを見て選んで 指でピースを移動させ 直接パズルにはめることができます 指をダブルタップして ピースをはめることもできます ジェスチャを使用して パズルを回転させたり動かしたりすることで 様々な角度から見ることができます このように 立っていても座っていても 快適にプレイできます 間接的な入力により 椅子にもたれながらでも ゲームをプレイできます 直接的な入力のほうが 適している場合もあります 例えば 活動量が多いゲームなどが そうかもしれません それにバーチャルオブジェクトを直接 操作したほうが楽しい場合があります これは「Super Fruit Ninja」という 宙を飛ぶ果物やメニューボタンをスライスする 直接的な入力を中心に デザインされたゲームです この入力タイプがゲームに適している場合は フィードバックを十分に加えて プレイヤーがオブジェクトに触れるたびに 満足感を得られるようにします
手の後ろで光る稲妻や 飛び散る果肉などの 視覚的なフィードバックを 組み合わせることもできます つぶれる音や飛び散る音などを 加えることもできます 触覚の反応はないですが プレイヤーは接触した瞬間に UIボタンなのか飛び交うパイナップルなのか 正確に知ることができます 直接的な入力と間接的な入力の両方のジェスチャを ゲームでサポートすることをお勧めします 実装するにはいくつかの方法があります ゲームは組み込みのシステムジェスチャに 応答することができます 2つ以上のシステムジェスチャを 組み合わせて ゲームが応答する入力を さらに細かく 制御することもできます 必要に応じて ARKitの ハンドトラッキングを使用して カスタムジェスチャを作成することもできます どの方法にするか決定する前に 組み込みのシステムジェスチャを使用する いくつかのメリットを覚えておきましょう 1つは プレイヤーがシステムジェスチャの 使い方をすでに熟知していることです プレイヤーはすでにそれらを使用して プラットフォームの 他のアプリやゲームを操作しています そのため ゲームの操作方法を 教える必要はありませんし 追加の機器も必要ありません すぐにゲームを始められます プレイヤーはいつでもジェスチャを選択し プレイすることができます 加えて visionOS上のどこに ゲームがあっても システムジェスチャはサポートされます 共有スペースからフルイマーシブまで あらゆるスペースで機能します 様々なシステムジェスチャを 使用することができます 最も簡単なのは オブジェクトを注視して 片手の2本の指をタップする方法です 2D画面のゲームでシングルタップを 入力に使用している場合 visionOSでは それを タップジェスチャに置き換えるだけです
ダブルタップにも応答させることができます ピンチして押さえたままにするジェスチャや ピンチしてドラッグするジェスチャもあります いずれもオブジェクトを 直接的または間接的に操作できます 両手を使用してオブジェクトを 拡大縮小したり回転したりできます 「What the Golf」は システムジェスチャを 使用してオブジェクトを間接的に制御する visionOSゲームの良い例です ボールを注視して ピンチして押さえたままにするジェスチャで ボールをアクティブにします 手を動かすと ボールの方向や 指を離した時に ボールに加わる力の大きさを制御できます
手に入力が引き継がれたので 自由に見回して狙いを定めることができます
ピンチした指を離すと ボールが飛び ホールインワンできました
システムジェスチャに 応答させるのはとても簡単です RealityView内に追加した タップを可能にする すべてのエンティティに InputTargetComponentと CollisionComponentが必要です 次に エンティティを含む RealityViewにジェスチャをアタッチし そのビュー内のエンティティが タップ可能であることを示します ジェスチャが検出されると ジェスチャのハンドラで応答できます システムジェスチャへの応答方法については 「Develop your first immersive app」 という昨年のビデオと developer.apple.comにある インタラクティブ性に関する ドキュメントをご確認ください Unityでゲームを開発している場合は Unity Input Systemを使用して ジェスチャを検出して応答できます タップイベントを受け取るにはゲーム オブジェクトに入力コライダーを追加します タップデータがWorld Touchイベントとして 利用可能になります 「Create immersive Unity apps」で 詳細をご確認ください システムジェスチャにはすぐに使える たくさんのジェスチャがありますが さらに柔軟性が必要な場合は システムジェスチャを組み合わせて ユニークなジェスチャを作ることができます 2つ以上のシステムジェスチャをペアにして それらが同時または順番に発生した場合 検出することができます ジェスチャにキーボードの修飾キーを 組み合わせることもできます また SpatialEventGestureを使用して Tap Begins、MovesまたはEndsなどの ジェスチャイベントに ローレベルでアクセスすることができます この機能は プレイヤーが両手を使用して 2つの異なるオブジェクトを 同時に操作している場合に 便利な機能です SpatialEventGestureを使用して 各アクションのターゲットを追跡します この例では 人工衛星の選択や移動 サイズ変更または回転を 同時に行うことができます システムは前のジェスチャが 終了していなくても 各ジェスチャが発生するたびに 認識します コードではこのようになります ドラッグジェスチャで オブジェクトを移動している時に simultaneously(with:)を追加することで 拡大および回転ジェスチャが行われた時に それらの両方をアプリに リッスンさせることができます これにより 複数のジェスチャ間の 遷移がシームレスになります ジェスチャの組み合わせ方法については 「Take SwiftUI to the next dimension」 という昨年のビデオと そちらのドキュメントをご確認ください プレイヤーにとって馴染みのある システムジェスチャとそれらの組み合わせは visionOSでゲーム入力を デザインする際に最適です 入力のレパートリーを さらに充実させる必要がある場合は 独自のカスタムジェスチャを定義できます ゲーム用にカスタムジェスチャを 作成する場合は プレイヤーが簡単に習得でき 覚えやすいものにする必要があります 直感的に操作できるように ゲーム内の動作にぴったり合った ジェスチャにしましょう カスタムジェスチャをデザインする際は プレイヤーが正しい操作をしていることを 認識できるよう ビジュアルエフェクトと音の両方によって 適切な量のフィードバックを追加してください 独自のジェスチャを定義するには ARKitを通じて完全な骨格ハンドトラッキングに アクセスする必要があります システムジェスチャとカスタムジェスチャを 同じゲーム内で組み合わせることもできます このBlackboxはそれらを独創的な方法で 組み合わせた良い例です Blackboxはオンボーディング中に 環境内に新しい泡を作る カスタムジェスチャを プレイヤーに教えます このジェスチャは単純かつ直感的なので 学びやすく覚えやすいです これはとても重要です これがゲームに出入りする 主な方法だからです ただし カスタムジェスチャは多用せず 控えめに使用してください Blackboxは 適している場合には 常にシステムジェスチャを使用します 例えば 泡を注視して指をタップすると 泡を弾けさせることができます
重要な点として Blackboxは visionOSのフルスペースに存在します ゲームが共有スペースでプレイされる場合 つまり ほかのvisionOSアプリが 同時に並んでいる場合 ARKitとハンドトラッキングは 利用することができません フルスペースでは mixed progressive またはfullの いずれであれ 表示されるアプリはゲームだけです Blackboxのように プレイヤーは 周囲の環境を見ることができます ゲームによっては周囲の環境を 新しい環境に置き換えることもできます カスタムジェスチャを作成する場合 ARKitと完全な骨格ハンドトラッキングは フルスペースで利用できます これは円の形をしたカスタムジェスチャを 作成する方法を示しています ハンドトラッキングに必要な すべての関節を確認します ワールド座標系で 位置を取得します 次に円の形をしたジェスチャの場合 両方の人差し指と 両方の親指の先端の距離を 確認します その距離が4cm未満なら ジェスチャが認識され ゲームが応答できるようになります Unityでゲームを開発している場合 Unityのハンドトラッキング パッケージを利用して プレイヤーの関節の情報にアクセスします UnityゲームをvisionOSに 展開する方法については こちらのビデオをご確認ください 直接的なジェスチャか 間接的なジェスチャか システムジェスチャかカスタムジェスチャか どのタイプのジェスチャを使用するにしても 能力に差があるプレイヤーのために 別の方法も用意しておきましょう 例えば「Synth Riders」では 両手や両腕を使用して オブジェクトに触るように 入力がデザインされています 片腕でしかプレイできない プレイヤーはどうなるのでしょうか このゲームの 設定には 片手モードでプレイするかどうか 選択するオプションが用意されており さらに右手と左手のどちらで プレイするかを選択できます これで右手だけでゲームを プレイできるようになりました これらのアクセシビリティの 使用例について検討して プレイヤーのために入力の代替方法を 組み込むことは重要です RealityKitを使用する場合 ネイティブのアクセシビリティ フレームワークを利用できます 様々な能力に合わせた デザイン方法については 「Create accessible spatial experiences」というビデオをご覧ください Unityでゲームを開発している場合 Apple Accessibilityプラグインを使用して すべてのアクセシビリティ機能に アクセスすることができます 詳しくは 「Plug-in and play」を ご確認ください 柔軟性に優れたシステムジェスチャと カスタムジェスチャにより ゲームの入力をデザインするうえで すでにたくさんの選択肢がありますが 場合によっては visionOSで利用可能な 物理的な入力デバイスを サポートすることもできます visionOSは iOSやmacOSがサポートする 全てのゲームコントローラをサポートします これにはXbox Series Xや Sony Playstation DualSenseが含まれます ゲームコントローラのサポートは 一度に2つ以上の入力が必要な場合 適切な選択肢となります または 他のプラットフォームからゲームを 移植する場合で すでにゲームがコントローラを中心とした 入力に基づいている場合にも有効です Bluetoothのキーボードやトラックパッドが ゲームに適した入力である場合に備えて visionOSでは それらによる入力も サポートされています
Bluetoothを介してvisionOSに接続された 物理的なコントローラやキーボード またトラックパッドからのゲーム入力には 簡単に応答することができます 同じデバイスはiOS iPadOS macOS visionOSすべてで動作します しかも どのプラットフォームでもゲーム コントローラフレームワークは同じです 複数のタイプのデバイスにわたって ゲームを展開している場合でも それらすべてで同じコードを使えます 物理的なコントローラは ウインドウ表示のゲームから フルイマーシブ空間まで visionOSのあらゆる体験に使えます アーケードゲームの「Wylde Flowers」は コントローラをうまくサポートしています ゲームコントローラがVision Proと ペアリングおよび接続済みである場合は そのコントローラによるゲーム入力が 自動的に有効になります これは非常に重要なことです コントローラが接続されたことを検出し 入力をそのコントローラで動作するように 切り替えることは プレイヤーに ゲームの設定メニューで スイッチを探させるよりも はるかに良い方法です Wylde Flowersの別の優れたところは ゲーム内のすべての操作を コントローラで行えることです プレイヤーがシステムジェスチャを使用して UIの一部にアクセスするようにすると 不便なだけでなく 混乱を招くでしょう ゲーム内のすべての操作に加えて UIの選択もゲームコントローラで できるように入力をデザインしてください
プレイヤーがゲームコントローラを 接続したかどうかは簡単に検出できます システムに接続された ゲームコントローラを通知する GCControllerDidConnectに オブザーバを 設定するだけです GCControllerDidDisconnectイベントも 必ずリッスンして ゲームコントローラがない場合に システムジェスチャなどのほかの入力形式が 使用されるようにします ゲームコントローラが接続されたという 通知を受け取ったら コントローラの特定のボタンの状態を ポーリングできます 必要であれば 入力状態が更新された時 通知されるように 変更ハンドラを設定することもできます キーボードとトラックパッドからの入力も 同じフローです 接続をリッスンして 入力をポーリングするか 変更ハンドラを設定します これはゲームコントローラを検出し それに応答するためのコードです オブザーバを設定して ゲームコントローラが接続されたという 通知が届くのを待ちます ゲームを起動する前にコントローラが すでに接続されていた場合でも visionOSに接続されたすべてのデバイスに ついて通知を受け取ることができます 通知を受け取ったら 入力変更ハンドラを設定するか デバイスで予想される入力がないか ポーリングできます 最後に visionOS 2特有のステップが 1つあります ゲームオブジェクトが含まれる RealityViewにゲームコントローラ インタラクションモディファイアを 追加します これはRealityViewに対する ゲームコントローラの入力が ゲームにより処理されることを示しています ジェスチャの場合と同じように アクションに対してフィードバックを 提供することが重要です CoreHapticsフレームワークを使用して 画面上のアクションに合わせて コントローラで振動をトリガします サウンドエフェクトも忘れずに追加して アクションに成功した場合はプレイヤーに すぐに視覚的なフィードバックを提供します ゲームコントローラフレームワークを 初めて利用する場合は 始めるにあたって 役に立つリソースが用意されています Unityエンジンを使うゲームの場合は Unity用のゲームコントローラ プラグインを使用して ゲームコントローラ入力をサポートできます 詳しくは こちらのビデオをご確認ください ここで様々な種類の入力について 対応しているスペースを見てみましょう システムジェスチャや 従来のゲームコントローラ またキーボードなどの ほとんどの種類の入力については 共有スペースのウインドウやボリュームから フルスペースまでのあらゆるタイプの スペースで対応しています カスタムジェスチャによる 入力に応答させたい場合は フルスペース向けにゲームを デザインする必要があります まとめると ゲームには プレイヤーにとって適切と思える入力を デザインするための様々な選択肢があります 組み込みのシステムジェスチャは プレイヤーが簡単かつ自然に使えます さらに柔軟性が必要な場合は カスタムジェスチャを1つか2つ 追加することを検討できます ゲームの種類によっては 物理的なコントローラをサポートし 入力の選択肢を広げることができます 最後にもう1つ iOSまたはiPadOS向けの既存のゲームがある場合 それをvisionOSでよりイマーシブ感のある ゲームに変身させる方法について 「Bring your iOS or iPadOS game to visionOS」で詳細を確認してください ご視聴ありがとうございました
-
-
5:16 - Respond to a tap gesture
// Respond to a tap gesture. struct ContentView: View { var body: some View { RealityView { content in // For entity targeting to work, entities must have an InputTargetComponent // and a CollisionComponent! } .gesture(TapGesture().targetedToAnyEntity().onEnded { value in print("Tapped entity \(value.entity)!") }) } }
-
7:08 - Combine dragging, magnification, and 3D rotation gestures
// Gesture combining dragging, magnification, and 3D rotation all at once. var manipulationGesture: some Gesture<AffineTransform3D> { DragGesture() .simultaneously(with: MagnifyGesture()) .simultaneously(with: RotateGesture3D()) .map {bgesture in let (translation, scale, rotation) = gesture.components() return AffineTransform3D( scale: scale, rotation: rotation, translation: translation ) } }
-
9:33 - Create and detect a custom circle gesture
// Create and detect a custom circle gesture. // Get all required joints and check if they are tracked. let leftHandIndexFingerTip = leftHandAnchor.skeleton.joint(named: .handIndexFingerTip) // ... // Get the position of all joints in world coordinates. let leftHandIndexFingerTipWorldPosition = matrix_multiply(leftHandAnchor.originFromAnchorTransform, leftHandIndexFingerTip.anchorFromJointTransform).columns.3.xyz // ... // Circle gesture detection is true when the distance between the index finger tips centers // and the distance between the thumb tip centers is each less than four centimeters. let isCircleShapeGesture = indexFingersDistance < 0.04 && thumbsDistance < 0.04 if isCircleShapeGesture { // respond to gesture }
-
14:00 - Detect a connected game controller
// Detect connected game controller. // Add handler for when controller connects. NotificationCenter.default.addObserver( forName: NSNotification.Name.GCControllerDidConnect, object: nil, queue: nil) { (note) in guard let _controller = note.object? as GCController else { return } // Add controller input change handlers. _controller.physicalInputProfile[GCInputButtonA]?.valueChangedHandler = { //... } } // Poll for controller input if controller.physicalInputProfile[GCInputButtonA]?.pressed {... } if controller.physicalInputProfile[GCInputButtonB]?.pressed {... }
-
14:24 - Tag a RealityView to handle controller input
// Tag a RealityView to handle controller input. struct ContentView: View { var body: some View { RealityView { content in // Tag your RealityView to respond to controller input events. } .handlesGameControllerEvents(matching .gamepad) } }
-
-
特定のトピックをお探しの場合は、上にトピックを入力すると、関連するトピックにすばやく移動できます。
クエリの送信中にエラーが発生しました。インターネット接続を確認して、もう一度お試しください。