VRC TriggerをUDONノードで再現する
うどん、こねてますか?
VRCがUnity2018に移行、SDK3+Udonに対応し、色んなギミックを搭載したワールドが作れるようになって1ヶ月。
ワールド制作の多くはU Sharp(U#)環境で書かれていると聞きますが、テキスト型プログラミングなんて触ったことのない方(僕もそうです)にはまだまだビジュアル型のノードは助かりまくっています。
ところで、SDK3ではこれまでのギミックの中核を担っていたVRC Triggerが使えず、Udonで代用する必要があります。
というわけで、VRC Triggerの各トリガーに対応する(or代用できる)ノードをざっくりまとめました。
はじめに
この記事では、簡単なEventの解説のみに留めています。(Actionsの解説はしません)
VRC特有の関数を除けば、大体の関数の使い方はググればC#等の記事が出てきます。
もちろんC#はテキストですが、ノードと見比べるとどういう挙動をするのかはある程度想像がつくと思いますので、実際に作りながら確かめてみると良いです。
Custom/OnInteract
他のほとんどのイベントはEventsから辿れるのですが、カスタムトリガーはSpecialから辿る必要があります。(何で?)
イベントのStringには適当な定義を書いておき、他から発火させます。
例えば、他Objectに設置したInteractイベントから発火させたい場合、以下のように設定します。
InteractイベントからUdon Behavior>Send Custom Event(発火を同期させたい場合はSend Custom Network Event)に繋げ、publicにチェックを入れたUdon Behavior>VariableでCustomイベントをくっつけているObjectを設定、Get Variableで取得しSend Custom Eventのinstanceに設定してeventNameを先程Stringに入れた定義名にすればOKです。(早口)
ちなみに、Send Custom EventのeventNameはString値で他コンポーネント(UiText等)から参照できるので、上手く使えばパスワードとかに使えます。
逆に、Customイベント側のStringは能動的に変更することは出来ません。
能動的に変更したい場合は、以下のようにBranch(いわゆるif)を使う方法があります。
Relay
対応する関数は無いので、発火させたいうどんの最後に全体に伝播させるCustomを発火させる等での対応になるでしょうか。
OnNetworkReady
そのまま対応する関数はありません。
再現するにはOnPreSerialization/OnDeserialization/OnPlayerJoinedのいずれかを使うことになります。
順に簡単な説明を書いておくと、
・OnPreSerialization:変数の同期前に発火
・OnDeserialization:変数の同期後に発火
・OnPlayerJoined:誰かがインスタンスに入った時に発火(後述)
といった感じです。
試していないので憶測になるのですが、OnPreSerialization/OnDeserializationは同じUdon BehaviorにSynced変数を入れていないと動かない気がします。
また、OnPlayerJoinedは「誰かが」Joinした時に発火するので、他プレイヤーが入ってくる度に発火します。
以下のように設定することで、自身の下でのみactionを起こすことができます。(たぶん)
やってることは「JoinしたプレイヤーのApiを取得し、ローカルプレイヤーのApiと比較、同じ(=Joinしたのが自分)なら発火」といった感じです。
ただ、OnPlayerJoinedとOnNetworkReadyは発火タイミングが恐らく異なる(前者はインスタンスに入った時、後者は入った後、ワールドの読み込みが終わった時)ので、タイミングを合わせたければOnPreSerialization/OnDeserializationを使う方が正しい気がします。
OnPlayerJoined/OnPlayerLeft
そのままEventにあります。下側の見切れてるやつでJoin/LeftしたプレイヤーのPlayerApiを取得することも出来ます。
OnEnterTrigger/OnExitTrigger/OnEnterCollider/OnExitCollider/OnParticleCollision
それぞれOnTriggerEnter/OnTriggerExit/OnCollisionEnter/OnCollisionExit/OnParticleCollisionがEventにあります。ついでに重なっている時に毎フレーム呼ばれるOnTriggerStayとOnCollisionStayもあります。下側のやつで「当たった相手のコンポーネント」を取得することも出来ます。
注意点として、Triggerが取得するのはCollider、Collisionが取得するのはCollisionの型であるということです。
クッッッッソ名前が似ていますが異なるものなので、それぞれ別の型には当然繋がりません。
また、OnParticleCollisionはGameObjectそのものを取得します。
OnPickup/OnPickupUseDown/OnPickupUseUp/OnDrop/OnEnable/OnDisable/OnSpawn/OnDestroy/OnStationEntered/OnStationExited/OnVideoStart/OnVideoEnd/OnVideoPlay/OnVideoPause/OnOwnershipTransfer
そのまんまEventにあります。ので全部省略!
OnKeyDown/OnKeyUp
Eventとしてはありません。UpdateイベントとBranchを使う必要があります。
UnityEngine>Input>GetKeyDown(Up)で特定のキーの押す/離すを取得し、BranchのTrue側にactionを書く感じです。Key Codeはリストで選ぶ場合、アホみたいにあるので頑張って下さい。
OnAvatarHit
Event内のOnControllerColliderHitが対応している・・・ようですが、現状機能していない模様。
同じような再現をする場合、PlayerLocalとのみ衝突するLayerを作成→そのLayerに設定したコライダー付きオブジェクトにOnTrigger/OnCollider系を付けて反応させる等で可能です。
OnTimer
対応する関数はありません。
ざっくり再現するなら、FixedUpdateを使うか、deltaTimeを使うかが挙げられるかと思います。
FixedUpdateに関してはほぼそのままなのでググってもらうとして、deltaTimeを使った例が下記になります。
これをコライダー付きのGameObjectにアタッチすることで、「インタラクトすると1秒毎に音がなるギミック(メトロノーム)」になります。
仕組みについてはカウントアップタイマーの応用です。ノードは複雑ですが、やってることは割とシンプルなので読み解いてみて下さい。
Update内2つ目のBranchの条件Greater Than Or Equalの下側をランダムに設定すればOnTimerの下限と上限を設定できます。
とはいえ、正直、固定時間間隔で発火させるならAnimatorでいいです。
OnDataStorageChange
VRC_DataStorageが無いので無いです。そりゃそうだ。
以上となります。
この記事が、まだまだノードをがんばる人の一助になれば幸いです。
この記事が気に入ったらサポートをしてみませんか?