【PlayCanvas】Oculusブラウザで動く自由に移動できるワールド(空間)をWebXRで実装してみました。
WebXR ( WebVR/WebAR ) Advent Calendar 2021アドベントカレンダー13日目の記事です。
PlayCanvasを使用してWebXR(Oculusブラウザ)に対応したプロジェクトの検証目的で作ってみたプロジェクトになります。ぜひこちらのリンクから試して頂いて感想などをいただけると嬉しいです。
↓↓↓↓
※ 注意
※ Oculus Quest / Oculus Quest 2の Oculusブラウザのみ対応確認しています。
実際の動作はこちらの動作です。また、Oculus Questから当該のURLにアクセスしていただけますと実施にVR空間に入ることができます。
PlayCanvasとは?
PlayCanvasとはWebGLベースのゲームエンジンのJavaScriptのライブラリです 。OSSのエンジンと、ウェブベースのエディタ存在しており、WebXRについても対応しており開発することができます。
PlayCanvas GitHub
PlayCanvas 日本公式サイト
PlayCanvasでWebXRの開発をするには?
PlayCanvasの公式リポジトリに、XRのExamplesがMITライセンスで存在しています。
こちらのサンプルを使用して開発をすすめる方法がおすすめです。今回のプロジェクトもキャラクターの移動とコントローラー(ハンドトラッキング)についてはこのプロジェクトを参考にさせていただきました。
基本的には上記のサンプルを見ていただくのがかなり参考になりますが、この記事はサンプルを利用して開発をしたときに工夫した主にシーン移動周りのことと少し嵌りそうなポイントのところを紹介します。
今回のプロジェクトはビジュアルエディターを使用して開発をしています。
またこのプロジェクトはこちらからコピー(Fork)をして使用する事ができます。
※パソコン(Google Chrome / FireFox)での開発はこちらの拡張機能を使用してください。
このプロジェクトは下記のシーンの構成で構築されています。
- Home (起動時に呼び出されるシーン)
- Lobby
- World 1
- World 2
また、シーンの遷移はこのようになっています。
Home(起動時のシーン) -> Lobby(VR) <-> World1(VR) <-> World2(VR)
VRの空間に入ったあとについては、ロビーとワールドを行き来できるようになっております。
シーンについての解説
Home(起動時のシーン)
起動時のシーンではVRに入るボタンの表示と音声の再生、カメラの準備等をしております。
このシーンのみOculusブラウザ以外の端末からも利用できるシーンとなっております。
ブラウザの対応状況における場合分けなどもこのシーンで行っております。
ボタンの表示について
HomeのシーンではVRのカメラに入る事とHTMLにてUIの表示を行っています。
UIの表示についてはこちらをご覧ください。
VRシーンに入る方法について
VR用のカメラに入る方法についてPlayCanvasではVRのシーンに入るためには事前にCamera
用のコンポーネントとエンティティを用意する必要があります。
Camera
コンポーネント内のメソッドstartXrを呼び出すことでVRのシーンに入る事ができます。
また、startXr
の第2引数にて着席 / ルームスケール等の指定ができます。
//カメラコンポーネント
camera.startXr(pc.XRTYPE_VR, this.XRReferenceSpaceType);
VRシーンに入った際のPlayCanvasのシーン移動について
VRに入るボタンを押された際にこのようなシーンの移動を行っています。のPlayCanvasではシーンをHome -> Lobbyに移動しています。このような処理を行っています。
async enterVrScene(sceneName) {
if (this.app.xr.supported && pc.XRTYPE_VR) {
const cameraEntityParent = this.app.root.findByTag("vrcamera")[0]; // VR用のカメラを取得
const cameraEntity = cameraEntityParent.children[0]; // VR用のカメラを取得
cameraEntityParent.enabled = true; // 非表示のVR用のカメラを表示に切り替える
cameraEntityParent.reparent(this.app.root); //
// ※※ シーンの移動前にreparentを使用して、VRカメラをRootのヒエラルキーの外に配置をしています。
// ※※ これによってシーン移動によってカメラが消えることが無くなります。
cameraEntity.camera.startXr(pc.XRTYPE_VR, this.XRReferenceSpaceType); // カメラコンポーネント内のstartXrメソッドを使用してVRのシーンに入る
const old = await this.loadScene(sceneName); // 新しいシーンの読み込み
old.destroy(); // 古いシーンの削除
}
}
Lobby(VRモードで最初に入るシーン)
このシーンではVRの移動とポータルによる別シーンへの移動をすることができます。
それぞれこのような形で実装をしています。
VRで移動について
VRでの空間移動についてはこちらのGitHubのコードを利用しています。
ポータルについて
このポータルはPlayCanvasのElement
コンポーネントを配置して使用しています。
動作としてはGoと書かれている部分をOculus Quest 2のコントローラーでクリックされた場合に別シーンへ移動をする仕組みとなっています。
VRの状態でもElementコンポーネントのHover / Clickについては動作するのでボタンが押されたらthis.app.fire
にてイベントを発火してシーンの移動をしています。
イベント発火用のボタン
class LoadSceneButton extends pc.ScriptType{
initialize(){
this.entity.button.on("click", async () => {
this.app.fire("vr:scene:change", this.sceneName);
});
}
}
pc.registerScript(LoadSceneButton);
LoadSceneButton.attributes.add("sceneName", {type: "string"});
呼び出される処理
vr:scene:change
のイベントを受け取った場合に新しいシーンを読み込み、古いシーンを削除しています。また、VR状態のカメラについては削除がされないのでそのまま同じエンティティを使用してシーンの移動をすることができます。
async changeVrScene(sceneName) {
this.app.root.findByName("CameraParent").setPosition(0, 1.5, 0); // シーン移動時にカメラの位置を初期化
const old = await this.loadScene(sceneName); // 新しいシーンを読み込み
old.destroy(); // 古いシーンを削除
}
World 1 / World 2(テスト用ワールド※遷移先)
World1,World2に関しては、実際にコンテンツを入れ込むシーンのテスト用のシーンとなります。Lobbyと似たような機能を持っております。ポータルによるシーンの移動のほかは基本的にはPlayCanvasの通常のシーンの構成となっております。
このシーンでは動画を読み込み流しております。
動画の読み込みについてはこちらをご覧ください。
このような形でPlayCanvasでは比較的かんたんにシーンの移動を実装することができます。
マルチプレイなどの機能を実装するとそれなりに面白い事ができそうではないかなと考えております。
なにかご質問等がございましたらTwitter: mxcn3までご連絡ください。
Discussion