状態の同期ズレを避ける
いわゆる同期ズレ現象のうち、状態設定のズレが起きる理由と回避方法について。
推測を含む不確実な内容ですが、解決の糸口になればと思い。
要点 TL;DR
- Toggle は一度ずれるとずれたまま。True, False 指定方式を検討する
- 別プレイヤーからの操作実行順は保障されないので注意(たぶん)
- 一時に大量のアクションが起こるつくりは避ける。Animation の使用を検討する
- バッファ指定を適切に選択する
各論
トグルの特性
真偽を指示する類のアクションでは動作指示に Toggle
が選べますが、これは「トグルせよ」という指示として通信されているようです。よって結果は受信側の現在値に依存します。特に「一度ずれるとずれたまま」になります。
(「発信側での現在値を参照してTrueだったのでFalseを送信する」のようなやりかたではない、という意味。ログを観察するとそう見える。)
単純なケース例えば「ボタンであるものをトグル操作する」というようなものでは、見た目のデザインを変えてしまいますが「True にするボタン」と「Falseにするボタン」に分けることで簡便に問題を解消できるかもしれません。
(同期ズレが起こる原因は他に在るので、これは根本的には直していない回避的な措置です。ですが、このように作り変えるのは簡単なので状況によってはこれを試みても良いと思います。)
マルチ環境でのアクションの順番
クライアント A とクライアント B からほぼ同時に発生したアクションが 「C の元では A→B の順で届き実行される」が 「D の元では B→A の順で届き実行される」ということが起こりえます。
これにより「C と D は異なった状況を見る」ということが起こります。 (A, B のアクションが両方ともトグルならば結果は同じですが)
(詳細な検証はできていませんが)これは不具合ではなく、おそらく仕様です。ワールド作成者が気をつけて仕組みを作る必要があります。
(ワールドにゲーム的なものを作って勝負判定がこの現象に依存していると、見ている結果が異なる事になり面倒なことになります。
Broadcast Type
の Master
をうまく使えばよさそうです。が使用ノウハウがまだ私にはありません。)
アクションの脱落(?)
大量のアクションが同時にマルチクライアント環境で実行されると一部のアクションが抜け落ちることがあるようです。ただしこれは観察からの憶測で、本当にそれが起こっているのか、不具合なのか仕様なのか、よく分かっていません。
回避的なつくりの方針として「動作指示だけを通信して詳細の実行は各クライアント内でローカルに行う」ということが考えられます。使えそうな道具としては animation と custom trigger があります。
(Unity に元からある Animation を使用した場合、VRChat のマルチクライアントの機構を通さずにオブジェクトの状態変化が実行されるので、動作負荷がきわめて軽いということが観察されています。)
(custom trigger を使って ActivateCustomTrigger は他クライアントに流れるようにして、その custom trigger の定義自身は Local
にすればよさそうです。が実地検証していません。)
バッファの選択
制御したいものが単純な機構の場合、
後からワールドに join する者のために状態を記録するバッファは、
最後の操作のひとつ分だけで十分です。
この場合 Broadcast Type
は AlwaysBufferOne
が適切です。
例えば Always
を選択すると、
後からワールドに join してきたプレイヤーがいると大量のアクション送信が行われます。
どうもその時にぬけがおこるのか、他プレイヤーの現在操作と混じるのか、詳しいことは分かっていませんが、状態のズレがおきがちなように見えます。
(追記)アニメーションを trigger ではなく int で駆動する
もう一つ同期ズレを起こしやすい遷移としてはAnimatiorのAnimationTriggerがある。
— 坪倉輝明@メディアアーティスト (@kohack_v) 2018年4月3日
TriggerはTrueになった順番は保たれないので複数のTriggerがTrueになるとクライアント毎に違うステートに遷移する。
VRC_TriggerからAnimationIntで明示的に遷移させるのが正解。#VRChat #VRCワールド開発Tips pic.twitter.com/KUHCVpgJCs
(Any State のみから遷移を書いているのが(のも)ポイント。)