日報

VR Chat関連の日報です

UIを使ってVR Chatで使える自作ワールドポータル集を作った話

VR Chatのホームワールドに、この画像のような自作ワールドポータル集を設置しました。

ポータル
自分のワールドへ行くときに、いちいちメニューを開いてスクロールして…みたいな手間を省けるのが便利。

以下どのようにして作ったかメモです。 ……が、私はプログラミング赤ちゃんレベルなので、強引に解決してる部分があると思います。
もっとスマートだったり、処理が軽くできる方法が多分あるはず。

Canvasの設定

UIを表示したい場所にCanvasを置いて、VR ChatでUIを使う準備をする。 これを怠ると「Unity上では動くのに、VR Chatでは動かない!」ってなる(なった)。

  • Canvasに「VRC Ui Shape」をアタッチする
  • CanvasのLayerを「Default」にする
    初期LayerのUIのままだと、VR Chat内でメニューを開いているときしか操作できないらしい

UIを配置

ボタンや画像をいい感じに置く。

Udon sharpを頑張って書く

自作ワールドポータル集では、Udon sharpの処理は以下の3つに分かれている。

  1. 画面更新処理
  2. ポータルを出すボタンの処理
  3. ポータルを消すボタンの処理

それぞれ処理の説明は以下。

1. 画面更新処理

画面下部にあるワールド指定のボタンを押すと、赤枠部分が指定の内容に変更される。

まず、タイトル、説明、画像の部分について。

画面下部にあるワールド名のボタンを押すと、対応する内容で赤枠部分が更新されるようにした。

①タイトルと②説明文について

タイトルと説明文は、UIのTextMeshProを使用している。 このオブジェクトを、指定の内容で書き換える対応を作成した。

最初はString型の文字列を渡して、UI TextMeshProのオブジェクトの内容(TextMeshProUGUI.text)を書き換えようかと考えていた。

改行コードを文字列の中に入れても反映されず、コードの中で処理しなくてはいけないらしい……ということを調べていた中で、String型はお勧めできないという記述を発見。(忘れちゃったけどメモリがどうとかだったような……???)
真偽は定かではないけれど、プログラミング赤ちゃんなので素直に従うことにした。

Hierarchyに置いた非表示のUI Textに更新をかけたい内容を設定して、その内容(Text.text)でTextMeshProのオブジェクトの内容(TextMeshProUGUI.text)を書き換えたら、ついでに改行問題も解決したのでよしとした。

非表示のUI Textはワールドの数×2個(タイトルと説明文)作成した。

③画像の更新について

画像はUIのImageを使用している。 UI ImageのSourceImageの内容を変更すれば、画面上で書き換わるみたい。

SourceImageに設定する画像は、Sprite形式にしておく必要がある。

Hierarchyに置いた非表示のUI Imageに更新したい画像を設定して、すでに表示されているUI Image(初期画像)の更新をかけることとした。

簡単に言うとこういうこと。

初期画像.sprite = 更新したい画像.sprite;

④ポータルを出すボタンについて

まずは、表示するポータルの準備。
GameObjectにVRC PortalMakerをアタッチして、RoomIdの中に"wrld"から始まるワールドのIDを設定する。ワールドのIDは、VR Chatのワールドのページから確認できる。
このGameObjectを表示状態にすれば、ワールド上にポータルが現れる。これをワールドの数だけ作る。

「ポータルを出す」ボタンは、これらのポータルのGameObjectを表示する役割を持つ。そのため、ワールドの種類分作成する。
ボタンの種類は、UI TextmeshProを使用した。

画面下部にあるワールドのボタンを押したら、単純に各「ポータルを出す」ボタンを表示すればいいでしょと考えていたけれど、そうもいかなかった。 なぜなら、同じ場所にどんどん「ポータルを出す」ボタンが重なって表示されるからである……。そりゃそうだ。

仕方ないので、全ての「ポータルを出す」ボタンを非表示する処理を行った後、指定の「ポータルを出す」ボタンを表示するような処理にした。

⑤ポータルを消すボタンについて

画面下部にあるワールド名のボタンを押したとき、すでに「ポータルを消す」ボタンが表示されてなかったら表示させる処理とした。

2. ポータルを出すボタンの処理

ボタンが押されたら、下記処理を行う

  1. ポータルのGameObjectを全部非表示にする
  2. 次に指定のポータルのGameObjectを表示する処理を行う。

3. ポータルを消すボタンの処理

ボタンが押されたら、下記処理を行う

  1. ポータルの表示を全部オフにする

ポータルを出すボタンから、表示をオンにする部分を抜いただけ。

使用アセット

Unity公式が配布しているボタンのテクスチャ集。

Udonを使う時の注意点

UI Buttonに直接Udon Behaviourをアタッチしても動作できないので、下記手順で対応する

  1. 空のGame Objectを作成して、InspectorでUdon Behaviourをアタッチする
  2. ButtonのButton(Inspector側)にあるOnclick()の+ボタンを押す
  3. Objectの部分に1で作成したGameObjectを設定する
  4. No Functionとなっている部分を、Udon Behaviour.SendCustomEvent(string)に変更する
  5. 入力欄が現れるので、実行したい関数名を設定する

最後に

行きつ戻りつしながら、だいたい2日くらいで作りました。

RoomIdの値を渡してVRC PortalMakerのRoomIdをいい感じに更新できればHierarchyがもうちょっとすっきりしそうなのですが、どうコードで書くのか分かりませんでした。(大して調べてないせいもありますが……。)
仕方ないので非表示のゲームオブジェクトずらずら&Inspectorで設定する部分が多い状態になっています。

とはいえ、やりたかったことができたのでおおむね満足です。