メインコンテンツまでスキップ

XRのUI

没入型セッションには、HUDを置くための平らな画面がありません。ユーザーはヘッドセットを通して、ARではスマートフォンのカメラを通してシーンを見ます。XRのインターフェースはワールド空間のスクリーン、つまりユーザーがコントローラーや手で指し示す、シーン内のパネルです。スクリーン空間のスクリーンは平らなディスプレイ向けに作られているため、XRでは使わないでください。

XR UI

パネルの構築​

パネルは、他のワールド空間のスクリーンと同じように構築し、サイズはメートル単位で決めます。スケールが0.001なら1単位は1ミリメートルで、解像度が800 × 500のスクリーンは幅80 cm、フォントサイズが32のテキストは高さ3.2 cmになります。モニターでは読みやすいテキストでもXRでは小さすぎることがあるため、結果はヘッドセットで確認してください。

パネルを置く場所によって、パネルの動き方が決まります。

  • ワールドに置く。 テーブルの上のコントロールパネルのように、部屋の決まった場所にあるパネルが最も快適です。ユーザーから腕の長さ〜2メートルほど離れた、目の高さより少し低い位置に、ユーザーの方へ向けて配置します。
  • 手やコントローラーに付ける。 コントローラーのエンティティの子にしたパネルは、手首のメニューのようにコントローラーと一緒に動きます。XrMenuスクリプトは、手とコントローラーに対してこれを行います。
  • 視界に追従させる。 カメラに固定したパネルは、ユーザーが何をしても視界の同じ位置に留まるため、多くの人が不快に感じます。代わりに、XrMenuの常時表示モードのように、ゆっくりと視界に追従させてください。

ポインティングとセレクト​

XRの入力は、アプリケーションのXRマネージャーであるapp.xrを通して処理されます。エディター、React、Web Componentsでは、XRマネージャーが自動的に作成されます。pc.AppBaseで作成したアプリケーションにXRマネージャーがあるのは、そのAppOptionsにoptions.xr = pc.XrManagerを追加した場合だけです。

セッションの実行中、ElementInputは毎フレーム、すべてのXR入力ソース(各コントローラーや手)のレイで、入力が有効なエレメントに対するレイキャストを行います。そして、エレメントで次のイベントを発火します。

イベント発火するタイミング
selectenter, selectleaveレイがエレメント上に入ったとき、またはエレメントから外れたとき
selectstartレイがエレメント上にある間に、トリガーを引く、ピンチするなどのセレクトが始まったとき
selectmoveエレメント上で始まったセレクトが続いている間、毎フレーム
selectendセレクトが終わったとき
clickセレクトがエレメント上で始まり、エレメント上で終わったとき

そのため、ボタンはマウスの場合と同じように、レイが指している間はホバー状態、セレクトで押さえている間は押下状態になり、ボタン上でセレクトが終わるとクリックされます。ボタンのclickリスナーは、XRのために変更する必要はありません。入力ソースの種類ごとにセレクトが何にあたるかについては、入力ソースを参照してください。

入力ソースの2つのプロパティが、インターフェースとのやり取りを制御します。

app.xr.input.on('add', (inputSource) => {
// 右手のコントローラーまたは手だけがインターフェースを指せるようにする
if (inputSource.handedness !== pc.XRHAND_RIGHT) {
inputSource.elementInput = false;
}
});

app.on('update', () => {
for (const inputSource of app.xr.input.inputSources) {
// この入力ソースが指しているエレメントのエンティティ。なければnull
const target = inputSource.elementEntity;
if (target) {
// 例えば、描画するレーザーを短くしてパネルで止める
}
}
});

XRの入力がどのエレメントにも届かないようにするには、useXr: falseを指定してElementInputを作成します。

ハンドトラッキング​

ハンドトラッキングでは、それぞれの手が独自のレイを持つ入力ソースになり、親指と人差し指のピンチがセレクトになります。エレメントやボタンは、コントローラーと同じように手に反応します。ハンドトラッキングを参照してください。

XRメニュー​

エンジンのXrMenuスクリプトは、リストからボタンのメニューを作成して表示します。表示する場所は、ユーザーの方に向けて開いた手のひらの上、コントローラーのボタンが押されたときのそのコントローラーの上、または視界に追従する常時表示のいずれかです。各項目は、選択されるとアプリケーションイベントを発火します。メニューのボタンの判定には独自のレイと指先のテストを使うため、コントローラーのレイでも、指先でボタンを直接押す操作でも機能します。

import { XrMenu } from 'playcanvas/scripts/esm/xr/xr-menu.mjs';

const menu = new pc.Entity('menu');
menu.addComponent('script');
menu.script.create(XrMenu, {
properties: {
menuItems: [
{ label: 'Restart', eventName: 'menu:restart' },
{ label: 'Exit', eventName: 'xr:end' }
],
fontAsset: font
}
});
app.root.addChild(menu);

app.on('menu:restart', () => {
restartLevel();
});

labelがありeventNameがない項目はボタンではなくテキストの行になり、setItemLabel()を使うとメニューの表示中に項目のテキストを変更できます。この例のxr:endイベントは、エンジンのXrSessionスクリプトがシーンにある場合にセッションを終了します。このスクリプトがそのイベントを処理するためです。スクリプトの働きについてはXRスクリプトを参照してください。XrMenuは、メニューが表示または非表示になったときにxr:menu:activeも発火します。

XR Menu

快適性​

  • パネルは静止させるか、ゆっくり追従させてください。視界に完全に固定しないでください。
  • 最もよく使うコントロールは、ユーザーが手を伸ばしたり振り向いたりしなくて済むよう、手が届きやすく見やすい場所に置いてください。
  • ボタンは大きくし、小さいボタンにはヒットパディングを付けてください。レイで正確に指すのは、マウスを動かすより難しいためです。
  • ボタンのホバー時のティントなどで、レイが何を指しているかを示してください。

XRの開始​

ブラウザが没入型セッションを開始するのは、クリックやタップなどのユーザー操作に応答したときだけです。エンジンのXRサンプルでは、キャンバスの上に重ねたHTMLボタンからセッションを開始しています。セッションの開始と終了の方法については、WebXRを使用するを参照してください。

関連情報​

  • ワールド空間UI - ワールド空間のスクリーンの構築と配置
  • 入力ソース - コントローラー、手、それらのレイとセレクト
  • ボタン - ボタンの状態、イベント、ヒットパディング
  • XR - PlayCanvasによる没入型のVRとAR