VRCでuGUIを使ってギミックを作る備忘録

プログラミングはからっきしなんだ

プログラミング教育ってヤツ、来年度から始まるらしいっすよ。

ってのはどうでもいいんですけど、生まれてこの方、中二病全盛期に頑張ってHyperTextMarkupLanguage(響きがかっこいい)を触った以外にプログラミングってやったことないんですね。

――てなことを最初に書こうと思ったんですけど、要点がズレまくるのでやめます。
簡単にこの記事の役割を説明しておくと、uGUIで使ってきた関数の備忘録です。

VRCにおける基本的なuGUIの使い方を知っている前提でまとめます。
下記記事から、「簡単なワールドメニューぐらいなら作れそう」って感じになってるといいです。
uGUI - VRChat 技術メモ帳 - VRChat tech notes
VRChatのワールドでuGUIを使う - Qiita
【VRChat】uGUIを使ったワールドメニューのサンプル公開+解説

また、あくまで自分の備忘録としてまとめるので、詳しいことはよくわからんがこうしときゃいい他の方が制作したギミックを覗いたらこうなってた使ったことない関数は載せてないことにご留意ください。

何故、uGUIを使うのか

ここもまぁ飛ばしてもらって構わないんですが。

ご存知の通り、VRChatでは現状、自作スクリプトは使えず、使える外部スクリプトは非常に限られています。
特にワールドを制作しようとするとココが厄介で、やりたいこと(ギミック)に大きな制限がかかってしまうんですよね。

で、じゃあワールドのギミックとしてまず使うのがVRC_Triggerだと思うんですけど、uGUIも使えるんだし色々便利なところもあるよねって感じです。

個人的にuGUIギミックの良さげなとこ・そうでもないとこを挙げると、
◆良さげ
・VRC_UiShapeを使うとレイキャスト(クイックメニュー出したときの青い線)が出る→カーソルが合わせやすい
・基本的にどこにいてもカーソルが合わせられる→インタラクト距離が実質無制限
色んな関数が使える→VRC_Triggerでは実現困難or不可能なギミックが作れる
・処理順が分かりやすい(上から処理されるはず)
・VRC_Trigger経由でも発動できるし、逆にVRC_Triggerを発動させることもできる
◆そうでもない
・Tooltipsが表示されないので、そこにネタを仕込むことができない
・同期がちょい面倒
・そもそも解説記事が全然無い
・ぼく「uGUIの使い方調べてみよっと!」→解説「こうやって自作スクリプトの関数を呼び出します」→ぼく「モ゜」

こんなところでしょうか。
面倒なとこも多いですが、色々と関数が使えるのはなんか楽しそうな気がしません?
まあなんとなく、ギミック開発の一助になればと思います。

使うのだ

というわけでここからが本題。まずはちょっとした基本知識から。

◆UIコンポーネントの種類

画像1

ひとえにUIと言っても色々あります。
まぁ各コンポーネント自体はVRCだけのものではないですし、ググれば大体の役割は見当がつくと思いますので省略。
ここでは関数が呼び出せる系のコンポーネントのうち、以下3つに絞って説明します。

・Button
その名の通りボタン。基本的にコイツを使うことが多い。多分。
シンプルながら色々できる良い奴だよ。

・Toggle
オンオフの状態を切り替えられる系ボタン。グループ化すれば「どれか一つだけオンになってる」的な使い方もできる。
オブジェクトの表示・非表示を切り替えたい時とかはこっち。

・Input Field
文字を直接入力できるイカした奴だよ。でもVRはキーボード使うのが手間なので、直接文字を入力しない運用をするよ。

他にも関数が呼び出せるコンポーネントはありますが、とりあえずこの3つを軸に行きます。
どれを使うべきかは、実装したいギミックと相談してください。

◆関数の種類について

とりあえず覗いてみると、色々な関数があることがわかります。

画像4

上の画像はToggleからGameObjectを見たときのやつです。
知っておきたいのは、( )の中です。
(string)とか(bool)とかそういうやつ。あるいは、前半に「bool ○○」とか書いてるやつ。
コイツは、実行するアクションに関わってきます。

よく見るやつを挙げておくと、
(bool):オンオフの状態を指定したものにします。(トグルじゃない)
(string):文字を代入します。
(Int)・(Float)
:Intは整数値を代入します。Floatは小数も使えます。
( )無し・記載無し
:押す度に実行します。
(Object)等
:指定されたコンポーネント等を代入します。

画像5

なんとなく知っとくと理解しやすいかも。

◆使っていくその前に

何も考えず絶対入れとけ!!!!!!!!!!!!!!!!!
(一応説明しとくと、通常状態ではイベント項目の入れ替えが出来ない上に、対象オブジェクトを変更すると、実行する関数が選び直しになるので三途の川を見ます。また、private関数を表示することも出来るのでヤバいでし)

◆実物を覗くのは大事

何もない状態から動作を考えるのはとても難しいです。
何かしらの完成品の動作を見ながら理解していくと良いでしょう。
ExMenu(拡張メニュー) v1.1
VRChatワールド用パスワードトリガー(StringTrigger)[VRChat]
僕は上2つの中身を覗きながら動作を確認してました。
一応、結果の自作物も置いときます。
【VRChat ワールド用ギミック】JPENPasswordSystem【ひらがなカタカナ英数字対応パスワード入力ギミック】

本題:使った関数をメモっていくぞ

最初にも挙げましたが、あくまで備忘録、実際に使った関数だけを載せます。
また、基本的に雰囲気で理解した気になっているだけなので、その辺ご留意ください。

◆GameObject

画像2

(Button)

画像3

(Toggle)

GameObjectそのものに関するものですね。

●SetActive
オブジェクトの表示・非表示を設定します。VRC_TriggerのSetGameObjectActiveと同じです。
(bool)は選択した状態への変更、Toggle側の( )無しはトグルです。
言わずもがな、結構使うやつですね。

●int layer
Layerを指定した値に切り替えます。

画像6

Layerってのはココのことです。VRCにおいては可視状態や衝突状態に関わる部分です。左の数字が切り替えるInt値です。
Layers - VRChat 技術メモ帳 - VRChat tech notes
VRChatのレイヤーについて(可視性/衝突判定)
このあたりが詳しいですね。
オブジェクトを複製してLayerを個別に設定→アクティブ状態を切り替えれば同じことが出来ますが、当然容量は大きくなるので、そういう時に使えます。

●BroadcastMessage(string)
Unityの説明を見てみると、

ゲームオブジェクトまたは子オブジェクトにあるすべての MonoBehaviour を継承したクラスにある methodName 名のメソッドを呼び出します。

とのこと。

C#やUnityに疎いぼく「?????????????」

ってなりましたが、要は指定したオブジェクトや、その下の階層のオブジェクトすべてにstringで指定した情報を一斉送信する、ってことだと思います。
メソッドは詳しくないですが、詳しい人は色々出来そうですね!(詳しい人はこの記事を見る必要はないのでは?)

とりあえず、これまでに使ったメソッドを挙げておきます。全部ExMenuの受け売りです。

・Press
Buttonを押すよって情報だと思います。つまり、情報を受け取ったオブジェクトのButtonのOnClick()を起動します。
単体だと(元のButtonやToggleにイベントを仕込めばいいので)意味は薄いですが、VRC_TriggerのCastomトリガー的な使い方が出来るのと、後述するTransformで親を入れ替えたオブジェクトのButtonを押せるのは便利です。

・DoActivateTrigger
Standard AssetsのActivate Triggerに設定したActionを実行します。
参考:UnityのUtilityにあるActivateTriggerを使ってみた
ギミックとしては、子にある複数のオブジェクトを一斉に非表示にしたりできます。
例えば10個のオブジェクトのうち、押した番号のオブジェクトだけを表示したいとき、本来なら「押した番号のオブジェクトを表示→それ以外の9個を非表示」で実現できます。

画像7

ただ、上のようにたくさん設定しないといけないのと、11個めのオブジェクトを追加したい場合、ボタン全てに変更を加えなければなりません。そうなるとめんどくさいですし、変更忘れによる不具合の原因にもなります。

そういう時にはActivate Trigger!(通販番組)

画像8

オブジェクトを一括選択してCreate Emptyで子に空のGameObjectを作り、

画像9

名前を変えつつAdd ComponentからActive Triggerを追加。
ActionをDeactivateに設定し、Repeat Triggerにチェックを入れて、

画像10

個別のTargetにそれぞれの親オブジェクトを設定。
ここが面倒ですが、後々オブジェクトを追加するときに複製すれば、自動で自分の親をTargetにしてくれるので楽です。
設定し終えたら、切り替えボタンに設定したButtonやTriggerを選択し、

画像11

上に親のオブジェクト(ここではtest)を選択、BroadcastMessage(string)を設定し、stringにDoActivateTriggerを記入。
下に表示したいオブジェクトのSetActive(bool)をオンにします。
先述の通り、上から処理されるので、これで全消し→No (1)だけ表示がされます。上下を間違えないようにしようね!(n敗)

あとめっちゃ間違えやすいんですが、Activate(アクティベート)でありActive(アクティブ)ではありません
見間違えると一生ギミックが起動しなくて無駄に悩むので気を付けましょう。いいですね!!!!!!!!!!!!!!!!!!!!

◆Transform

画像12

色々使えそうなものはありますが、まだ余り使ったことがないため一個だけ。

●SetParent(Transform)
指定したオブジェクトを、Transformに入れたオブジェクトの子に移動させられます。要はオブジェクトの子を移動できるやべーやつ。

画像13

例えば上のように設定すると、(親子関係ですらない)GameObjectをtestの子に移動させることができるわけです。

子に設定できるということは、親のアクティブを弄れば表示・非表示を合わせられますし、上に書いたBoradcastMessage(string)を受け取ることもできちゃいます。

使ってみた例がこちら。色々仕込んではいますが、こんな感じでPickupによって動くオブジェクトを能動的に切り替えることができたりします。
また、SpawnObjectで生成したオブジェクトに後から干渉する使い方も(ExMenu内のpropspawnerがそれ使ってた)。

◆Text

画像14

で、でかすぎる!(あのEasyEventEditorのせい)
こんだけあるのに紹介するのは一個だけです。

●string text
テキストの文字をstringに入力した文字に変更します。地味だがよく使う系。VRC_TriggerのSetUITextと同じ。
rich textを設定していればちゃんとタグも反映されるよ!

紹介が一個だけなのは他を使っていないからですが、上の方にあるメソッドはどういうものか察しはつくと思います。

◆InputField

画像15

画像16

多すぎてオーイシマサヨシになったわね・・・
とはいえこれも紹介するメソッドは少しだけです。まあ基本はtextと同じ感覚で使えるっぽいので多少はね?

●Append(string)
stringに設定した文字をInputField内の文字に追加できます。いいですか?変更じゃなくて追加です。
つまりは、VRモードでも疑似キーボードが使えるようになります。やべぇ。
stringを空にしておけば全クリアもできます。

更に言うと、後述しますがInputFieldは入力された文字列をstringとして他のメソッドに送信できます。やりたい放題じゃん・・・

●UpdateLabel()
そんな便利なAppendですが、それだけだとデータを持ってるだけで、テキストとして表示されません。
なので、Appendより下(最下部がいいと思います)にこれを置いておきましょう。
これによりテキストが更新されます。逆に言えばこれがないとテキストが更新されないので、そういうギミックもアリかなって思います。

画像17

こんな感じで設定すれば、ボタンを押す度に「あ」が入力されていきます。

●Backspace
文字通り、一文字削除です。こっちはUpdateLabelは必要ありません。

●SendOnSubmit()
Input Fieldコンポーネントの下側、On End Edit (String)を起動します。
Appendによって入力したstringの文字列を他メソッドに送信するために使います。

◆On End Edit (String)

画像18

Input Fieldコンポーネントにあるやつです。下のやつ。
文字入力が終わった時に起動する他、上記のSendOnSubmit()で起動させることもできます。

画像19

上はText選択時ですが、ButtonやToggleと同じメソッドもありますが、重要なのは赤枠で囲まれた部分。
ここのメソッドで、Input Fieldの持つstringを送信することができます。

画像20

例えば、textを設定すると、起動時に別オブジェクトのtextを入力した文字に変更します。

これを応用すれば・・・

画像21

ExecuteCustomTriggerを設定した例。入力された文字と同じ定義のVRC_Trigger>Customを起動します。
文字列がカスタムトリガーの定義に存在しなければ不発するだけなので、パスワードなんかに使えます。使いました。

◆VRC_Trigger

画像22

VRC_Triggerの各種トリガーを起動できます。アクション自体はVRC_Trigger側で設定します。ButtonやToggleで使うのはInteract()で何とかなる事がほとんどだと思います。或いは、先述したExecuteCustomTriggerの起動のどちらか。

●Interact()、ExecuteCustomTrigger(string)
OnInteractやCustomによるアクションを起動します。
uGUIによる入力は全てLocalですが、ここで設定したVRC_TriggerによるアクションはBroadcast Typeの影響を受けるため、アクションの同期が可能になります。
Customのstringはカスタムトリガーの定義なので、起動するアクションを個別に設定したり、Input Fieldの文字列を送信したりできます。

◆VRC_Pickup

画像23

ギミックとして利用できそうなのはほぼないですが、Dropは使うことも多々あるので一応紹介。

●Drop()、Drop(Int)
Pickupしているオブジェクトを強制的にドロップさせます。使いみちは色々あると思います。
Intの有無の違いは分かりません。なんかどっちでも動作するらしいよ。じゃあIntの方いらねーじゃねーか!

◆VRC_SceneResetPosition

画像24

そもそもこのコンポーネント自体が少し特殊で、他コンポーネントから関数で呼び出さないと実行されません。
というか古いコンポーネントらしく、VRCの公式ドキュメントにも記載されてないみたいです。が、代用品がなんか不具合あるみたいで大体こっちが使われてる印象。

●ResetPosition()
VRC_Scene Reset PositionコンポーネントのPositionで指定されたオブジェクトのTransformをコピーします。
要はその位置にオブジェクトをワープさせる機能ですね。
ただし、RotationやScaleもコピーされてしまうため、元オブジェクトと同じScaleにしないと大きさが変わってしまうので注意。
ちなみに、Positionを選択しない(Noneにしておく)ことで、元々そのオブジェクトがあった位置に戻すことが出来ます。(多分この使い方がメジャー)

◆その他雑多なもの

特筆するものでもないもののメモ

●Image.sprite(sprite)
●RawImage.texture(Texture)

ImageやRaw Imageの画像を変更。


VRC_TriggerからuGUIイベントを呼び出す

ここまで挙げた関数は、VRC_Triggerから間接的に呼び出すことも可能です。

例えば、
・押したらピックアップ可能なオブジェクトの位置をリセットするスイッチ
・乗ったら文字入力されるマット型キーボード
なんかも作れたりします。

画像25

まず、AnimatorとButtonを追加し、AnimatorにはAny StateからAnimationに矢印を伸ばします。
遷移条件に適当なTriggerを設定しておきましょう。
Buttonには実行したいイベントを入れておきます。TransitionやNavigationはNoneで大丈夫です。

画像26

次に、Animationウインドウから、上記赤枠で囲った部分をクリックします。そうすると、右側にちらっと棒が追加されたと思うので、選択します。

画像27

すると、InspectorにAnimation Eventが表示されているので、FunctionをPress()にします。

画像28

あとはVRC_TriggerのAnimationTriggerを実行すれば完了!

VRC_TriggerのBroadcastTypeをLocal以外にすれば、同期するuGUIイベントが作成できます。


おわりに

VRChatにおけるuGUIといえば大体がワールドメニューへの利用だと思うのですが、色々出来るんやでってのが何となく伝わればいいかな~~~って思ってます。
uGUIそのもののデザインはやや難解ですが、使いこなすことができれば応用的なギミックが作れたりするでしょう。
かくいう僕も全然使いこなせてないですけどね。

まぁなんていうか、ギミック仕込みの一助になれば幸いです。

この記事が気に入ったらサポートをしてみませんか?