はじめに
どうも。「バーチャルためにならない改変お姉さん」の水無月せきなです。
記事を書いている間に VRChat が Unity 2019 に移行していました。自分が使っている SDK の古さに驚いていたのですが、Unity も VRChat クライアントのバージョンも古いものとなってしまいました。読まれる方には大変申し訳なく思いますが、移行直前に解決したことのお話なのでお許しを……
さて前回は、物を出し入れするのに少し凝ったことをやろうとした話をしました。今回はその続きで、実装時に頭を抱えた、同期に関してのお話です。
環境
Unity:2018.4.20f1
VRChat:VRChat 2021.3.1(Build 1114)
VRCSDK:VRCSDK3-AVATAR-2021.01.28.19.08_Public
ここから先は憶測を含みますので、その点ご了承ください。
実装時に起きた問題
###「同期するはずなのに同期しない」
Avatars 3.0 の導入当初、「SDK2 のアバターと違い、後から来た人にも同期される」というのを見た覚えがあります。
その高い自由度とともに、「同期される」というのは1つのキーワードだった気がしますが、だからと言って絶対に同期されるわけではありません。
そう、__目の前で見ている人にすら同期されない__ことも起こりえます。
(実例が今回の私です)
どの記事で見たかという記憶は定かではないですが、「ステートマシンではなくパラメータの値が同期されるため、遷移の組み方によっては意図したように相手に見えない(つまり『同期されない』)ことはある」ということで、私もわかっていたつもりでした。
そんな私が当初組んでいた(そして同期しなかった)、オブジェクトの ON ・OFF に関するレイヤーがこちらです。
条件と処理の流れは以下のような感じです。
1: ON にするパラメータは True 、既に ON になっているオブジェクトは0個
⇒ 個数のカウントを1、オブジェクトを True に。
2: ON にするパラメータは True 、既に ON になっているオブジェクトは1個
⇒ 個数のカウントを2、オブジェクトを True に。
3: ON にするパラメータは False 、既に ON になっているオブジェクトは1個
⇒ 個数を0、オブジェクトを OFF に。
4: ON にするパラメータは False 、既に ON になっているオブジェクトは2個
⇒ 個数のカウントを1、オブジェクトを OFF に。
(番号を振り忘れましたが、右に流れるルートはキャンセルするルートです)
ON になっているオブジェクトの個数は、Bool のパラメータをビットに見立てた2進数として保持しています。
また、途中のステートマシンに付けた VRC Avatar Parameter Driver でこのパラメータの値を変更しています。
以上が概略ですが、このように実装したら、他の人に同期されませんでした。具体的な例を挙げると、「何も持っていない状態からオブジェクトを ON にすると、メニューから OFF にしても他の人からはずっと ON の状態になる」というものです。
原因は、__1.トランジションの条件で参照するパラメータの値を、その遷移先のステートマシンで変更していたこと 2.なおかつそれを考慮した条件設定や遷移の組み方をしていなかったこと__でした。
「同期しているから『同期しない』」
わかりにくい表現となってしまったので、「1.トランジションの条件で参照するパラメータの値を、その遷移先のステートマシンで変更していたこと」から行きましょう。
まず「パラメータの値が同期される」ということについて、パラメータの値が変わる度に同期が行われるのだと私は思っていました。つまり、メニューを操作してパラメータの値が変更されると__すぐに__他の人に同期され、それぞれで Animator 上の移動処理が__すぐに__行われると思っていたわけです。
また、途中のステートマシンの前後では通過するように条件を設定しており、ここでパラメータの値を変更しても、既にルートに入っているので大丈夫だと思ったのです。
しかし今回の事象を見る限り、私の認識は間違っていたようです。
トランジションの条件と移動後の私側で、ON になっているオブジェクトの個数を示すパラメータの値をまとめます。
(1・2は OFF ⇒ ON 、3・4は ON ⇒ OFF)
ルート | 1 | 2 | 3 | 4 |
---|---|---|---|---|
条件 | 0 | 1 | 1 | 2 |
移動後 | 1 | 2 | 0 | 1 |
何もオブジェクトを ON にしていない状態から OFF ⇒ ON ⇒ OFF にした場合、私の側では1・3のルートを通ります。他の方から見てもそうなるように期待したわけですが、ならなかったのは何度も書いている通りです。
「ON になったらずっと ON になっているように見える」ということから1・2のどこかで止まっていることは確実なので、3・4で余分な物である VRC Avatar Parameter Driver をとりあえず無効化してみました。
すると、同期します。
「原因はお前か!」
ですが、1・2では有効化したままで同期されているので、VRC Avatar Parameter Driver 自体が原因ではありません。
1・2では有効化したままでも同期され、3・4では有効化した途端に同期されなくなります。何が違うのでしょうか。
改めて表を見ましょう。
ルート | 1 | 2 | 3 | 4 |
---|---|---|---|---|
条件 | 0 | 1 | 1 | 2 |
移動後 | 1 | 2 | 0 | 1 |
私が1のルートを移動すると個数のカウントは1になり、2のルートの条件を__満たします__。しかし、3のルートを移動すると個数のカウントは0になり、3・4どちらの条件も__満たしません__。
ついでに、3・4で VRC Avatar Parameter Driver を無効化した場合は1・2の移動後の値のままなので、3・4どちらの条件も__満たします__。
仮に、パラメータの同期がメニュー操作後すぐではなく、私の Animator 上の移動が終わってから同期しているなら、今回起きた同期ズレは説明がつきます。
つまり、__パラメータの値の同期はアバター着用者側での Animator 処理終了後に行われる__ため、条件を満たさないように値を変更していれば当然状態がズレるということです。
同期の仕様についてはあくまで状況から導いた仮説であり、未検証のものです。しかし、これを踏まえた上でやり直したのが前回であり(ON・OFF の部分は別のやり方ですが)、こちらは一応同期も確認できたので、まあまあの確からしさはあるのかなと思っています。
では、「2.なおかつそれを考慮した条件設定や遷移の組み方をしていなかったこと」に移りましょう。
今回のような同期ズレを起こさないためには、トランジションの条件で参照するパラメータの値を(少なくともそのレイヤー内では?)変更しないことが一番でしょう。
ただ、私にはどうしてもそれが出来ない部分がありました。
なので次善の策として、変更しない別のパラメータを用意してトランジションを追加するなり、「途中で変えた値で同期する」ことを考えた設定・遷移の組み方をするしかないのかなと思います。
おわりに
VRChat のアップデートで Bool のパラメータが解禁された際、同じようなことをしようとして同じように同期しなかった時がありました。
その時は理由がわからなかったのですが、ようやく自分なりに原因を知ることができました。長かった……
「 Avatars 3.0 のアバターでも同期ズレすることはある」というのはこういうことを言われていたのでしょうし、既に誰かが書かれているかもしれません。
自分の浅学さを恥じる次第です。
同期の確認と原因究明にあたっては私のフレンドさん達、特にライルさんに協力していただきました。ありがとうございました。
どなたかのお役に立てば幸いです。それでは。