Programming in VRChat

VRChat でのプログラミングについて調べたことの書き溜め

アニメーション遷移条件を利用した MasterLocal の実現の解説

はじめに

VRChat のワールドに複雑な機構を持つギミックを作ったりリアルタイム操作を伴うゲーム的なものを作った場合に、 broadcast type として「マスターでのみのアクション実行」になるものが欲しくなる場合がある。 これは俗に MasterLocal と呼ばれていて要望も出されている( https://vrchat.canny.io/feature-requests/p/add-masterlocal-and-ownerlocal-trigger-types-for-trigger-system )。

それを実現しているプレハブがこちら:

この記事では実装の要点を解説する。

問題

現状で MasterLocal を作る時に問題になるのは、broadcast の設定で trigger の処理実行を master のみに限定する事は出来るが、その中で行うアクションが non-master に伝播してしまうという性質である。このプレハブの巧妙なキモは、その“届いてしまう”アクションの実効性を無くしている所にある。

この先を読み解く前提知識

broadcast を Local にした trigger の中から、同じく Master にした CustomTrigger を呼ぶ場合、その CustomTrigger は master でのみ発火する。ただしその中のアクションの実行指示は master から他の non-master プレイヤーのもとにも届き、アクションは実行される。通常結果的に master と non-master で同じ処理を行ってしまい MasterLocal すなわち「マスターでのみのアクション実行」にはならない。

仕組み要点

二つの boolean を Animation の遷移条件で論理和にしていて、一方が“届いてしまう”分で、もう一方がそれを無効化する意味になっている。無効化する方(PublicCall)は一連の動作ですぐに false にされていて、“届いてしまう”方(MasterCall)が master から届いても論理和が成立しない。一方 master ではこの false にする action (を納めている Custom trigger CallEnd)の Delay が 0.1 になっていて、論理和が真になる隙間時間が確保されている。

この隙間時間は non-master においても存在するわけだが、初めのトリガー(このプレハブの場合 OnPlayerLeft)が master と non-master でほぼ同時に実行開始されマシンの性能が同程度であれば、master から non-master へアクションの実行要求がネットワークを通して届く間に隙間時間が経過するので、論理和が成立しない。

各クライアント間のネットワークの通信速度にもとづくタイミング依存になっているので、non-master においてこの隙間時間に master から“届いてしまう”という事は仕組みの上ではあり得る。経験則的には起こらず通常はこの実装で問題は起きない。

注意点

このプレハブでは OnPlayerLeft(と OnEnable)を動作開始に使っているが、他のトリガーでもこの機構は動かせる。ただし頻繁に発生するトリガーでは、前のトリガーから発生した“届いてしまう”MasterCall 設定が、次のトリガー発火による隙間時間に偶然に納まってしまうことが起こりうるので注意が必要である。このプレハブでも複数人が一斉に OnPlayerLeft を引き起こした場合にそのケースは起こりうる。