VRC Rogue 2026/05/21

概要
オーナー交代後に参加した late joiner へ現行画面が届かない経路と、離脱済みオペレーター ID が残ったまま再開できなくなる経路を見直しました。
変更点
同期
- 再送処理を共通化しました
GameManagerに_RebroadcastCurrentState()を追加し、現在のローカル状態を sync 変数へ詰め直したうえでGameManagerとDungeonGeneratorを連続再送するようにしました。RequestSyncFromOwner()、OnPlayerJoined()、OnOwnershipTransferred()の3経路を同じ再送処理へ統一しました。
- 再送前に ownership を揃えるようにしました
GameManagerowner だけが更新され、DungeonGeneratorowner が別クライアントのまま残るとダンジョン同期だけ空振りするため、再送直前に両 Behaviour の ownership を取り直すようにしました。- ownership が揃わず再送できなかった場合は、
[REBROADCAST_SKIP]ログでGameManager/DungeonGeneratorの owner を確認できるようにしました。
- 離脱済みオペレーターを未設定と同じ扱いにしました
_IsOperatorAbsent()を追加し、_syncOperatorIdが残っていても対象プレイヤーが既に離脱している場合はSTARTと権限取得を通せるようにしました。StartOrRequestSync()、RequestOperator()、ReturnToStart()で同じ不在判定を使うように揃えました。
修正
- オーナー交代後に入室したユーザーの画面が同期されない
- 原因:
GameManagerの owner 交代後、late joiner への再送でDungeonGenerator側の ownership が揃っていないままRequestSync()が走ると、GameManagerだけ再送されてダンジョン同期が送られない経路がありました。 - 対応: 再送の入口を
_RebroadcastCurrentState()に統一し、再送前に両 Behaviour の ownership を確保してからGameManagerとDungeonGeneratorの状態をまとめて再送するようにしました。
- 原因:
- オーナー離脱後に誰も再開できない
- 原因:
OnPlayerLeft()が離脱したオペレーターの_syncOperatorIdを保持する設計のまま、StartOrRequestSync()とRequestOperator()が-1以外をすべて「現役オペレーターあり」とみなしていました。 - 対応:
_syncOperatorIdが指すプレイヤーの実在をVRCPlayerApi.GetPlayerById()で確認し、不在ならSTARTと権限取得を許可するようにしました。
- 原因:
設計メモ
- late joiner 再送は owner の種類ではなく「同期対象一式」で扱う
GameManagerだけ owner であっても完全な再送にはならないため、late joiner 向け再送はGameManagerとDungeonGeneratorを一体で扱う方針にしました。
次に確認すること
- VRChat Build & Test で、初期 owner 離脱後に別ユーザーへ owner が移った状態から、さらに新規参加者が入ったときに画面復元できるか確認が必要です。
- VRChat Build & Test で、オーナー離脱後に observer が
BACK TO STARTからSTARTを押して新しいオペレーターになれるか確認が必要です。 output_logでOnOwnershipTransferred、[JOIN_SYNC]、[REQ_SYNC]、[REBROADCAST_SKIP]の並びを確認し、再送失敗時の実機ログを採取する必要があります。