途中参加者と同期の問題
プレイヤーがVRChatのインスタンスに途中参加し、いくつかの同期変数が変更された後、そのプレイヤーはワールドの最新の状態に追いつく必要があります。このガイドでは、途中参加者にも一貫した同期されたワールド体験を提供する方法を解説します。
VRChatにおける途中参加者の処理方法
新しいプレイヤーがインスタンスに参加すると、VRChatは以下の処理を行います:
OnDeserializationイベントを通じて、最新のSynced Variableの値を送信します。- オブジェクトのオーナーを適切なプレイヤーに設定します。
- イベントはreplayedされません。
途中参加者に正しい状態を表示させるには
1. 状態の管理にはイベントではなくSynced Variableを使用する
イベントは一度しかトリガーされず永続しないため、途中参加者はイベントベースの変更を見逃してしまいます。代わりに以下の方法をとってください:
- 重要なデータは
UdonSynced変数に保存します。 - 手動同期(Manually)のUdonBehaviourを使用している場合は、同期データを変更した後に必ずオーナーが
RequestSerialization()を呼び出すようにします。
例:ドアを開けるためにイベントを送信するのではなく、変数を同期させます:
[SerializeField, UdonSynced] private bool isDoorClosed;
public void OpenDoor()
{
isDoorClosed = false;
RequestSerialization();
}
途中参加者が加わった際、正しくisDoorClosedの状態を受け取ることができます。
2. 途中参加者のためにオブジェクトの状態を補完する
プレイヤーが参加した際に変更を適用します。これは、読み込みが完了した時点で発生する OnDeserialization イベントで行うことができます:
private GameObject lockedDoor;
public override void OnDeserialization()
{
// show or hide the door depending on its synced state
lockedDoor.SetActive(isDoorClosed);
}
3. イベントと同期変数を必要に応じて組み合わせる
必要であれば、イベントから同期変数を変更することも可能です。例えば、誰かがドアを開けるたびにドアの同期状態を更新したい場合は、オブジェクトのオーナーに対してイベントを送信できます:
public override void Interact()
{
SendCustomNetworkEvent(NetworkEventTarget.Owner, nameof(OpenDoor));
}
これにより、変数を設定するためだけに、ドアのオーナーをインタラクトしたプレイヤーに変更する必要がなくなります。
最終更新: