VRC Rogue 2026/05/21


概要

オーナー交代後に参加した late joiner へ現行画面が届かない経路と、離脱済みオペレーター ID が残ったまま再開できなくなる経路を見直しました。


変更点

同期

  • 再送処理を共通化しました
    • GameManager_RebroadcastCurrentState() を追加し、現在のローカル状態を sync 変数へ詰め直したうえで GameManagerDungeonGenerator を連続再送するようにしました。
    • RequestSyncFromOwner()OnPlayerJoined()OnOwnershipTransferred() の3経路を同じ再送処理へ統一しました。
  • 再送前に ownership を揃えるようにしました
    • GameManager owner だけが更新され、DungeonGenerator owner が別クライアントのまま残るとダンジョン同期だけ空振りするため、再送直前に両 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 を確保してから GameManagerDungeonGenerator の状態をまとめて再送するようにしました。
  • オーナー離脱後に誰も再開できない
    • 原因: OnPlayerLeft() が離脱したオペレーターの _syncOperatorId を保持する設計のまま、StartOrRequestSync()RequestOperator()-1 以外をすべて「現役オペレーターあり」とみなしていました。
    • 対応: _syncOperatorId が指すプレイヤーの実在を VRCPlayerApi.GetPlayerById() で確認し、不在なら START と権限取得を許可するようにしました。

設計メモ

  • late joiner 再送は owner の種類ではなく「同期対象一式」で扱う
    • GameManager だけ owner であっても完全な再送にはならないため、late joiner 向け再送は GameManagerDungeonGenerator を一体で扱う方針にしました。

次に確認すること

  • VRChat Build & Test で、初期 owner 離脱後に別ユーザーへ owner が移った状態から、さらに新規参加者が入ったときに画面復元できるか確認が必要です。
  • VRChat Build & Test で、オーナー離脱後に observer が BACK TO START から START を押して新しいオペレーターになれるか確認が必要です。
  • output_logOnOwnershipTransferred[JOIN_SYNC][REQ_SYNC][REBROADCAST_SKIP] の並びを確認し、再送失敗時の実機ログを採取する必要があります。

vrchat udonsharp unity gamedev devlog