【World制作】 VRC_Rogue DevLog_20260506

作業内容

  • VRChat ワールド上にゲーム画面を表示するための土台(シーン)を構築開始
  • 複数のプレイヤーがワールドに入ったとき、全員に同じゲーム状態が見えるようマルチプレイヤー同期を実装
  • ゲーム開始前のタイトル画面を実装(AA アートのタイトルロゴ表示含む)
  • スタート画面 ↔ ゲーム画面 の切り替えと、画面レイアウトの調整
  • 「ゲーム操作ができる人(オペレーター)」と「見ているだけの人(観戦者)」の権限管理を実装
  • キャラクターが自動移動している間は、誤タップを受け付けないよう制御を追加
  • 連続タップによる操作の暴走を防ぐクールダウン機能を追加
  • マップ生成・メッセージログ(直近8行)をマルチプレイヤーに同期する仕組みを実装
  • 権限まわりのバグ修正
    • VRChat ワールド内にゲームログ表示ウィンドウを新規実装
  • ゲーム画面パネルの真下に「直近8行のメッセージログ」を常時表示するパネルを追加
  • ワールドに後から入ってきたプレイヤーも、入室時点で最新のログを見られるよう対応
  • ログパネルの配置・見た目(黒背景・サイズ)をエディタースクリプトで自動生成するよう対応
  • 同期用ログウィンドウの実装
  • スタート画面に戻るボタンの実装

実装のポイント(UDON)

同期設計: フルステート + Manual + BatchedSync パターン

  • BehaviourSyncMode.Manual + [UdonSynced] でプレイヤー状態・ゲームフラグを全フィールド同期
  • _syncPending フラグ + SendCustomEventDelayedSeconds(nameof(_DoSync), 0.3f) によるスロットル(BatchedSync)で、1ターン内の複数変更をまとめて1回の RequestSerialization() に集約
  • OnDeserialization で受信側がローカルコピーに展開し、表示を再描画

オーナーシップと操作権限の分離

  • 当初 SendCustomNetworkEvent(Owner, ...) + [NetworkCallable] で「オーナーが権限を付与」する設計を試みたが、引数付き NetworkCallable のコンパイルエラーが発生
  • 最終的に 「権限を取りたい人が自分でオーナーシップを取得して直接書き込む」 設計に変更(_AcquireOwnership() → _syncOperatorId = LocalPlayer.playerId → RequestSerialization()
  • _syncOperatorId == -1 のガードで二重取得を防止

マップ再生成の無駄な再計算を抑制

  • OnDeserialization のたびに Generate() を呼ぶと重いため、_lastBuiltSeed / _lastBuiltFloor で変化検知し、seed か floor が変わった時だけ再生成するよう最適化

ゲーム状態フラグの bit pack

  • isGameOver / isCleared / hasAmulet / isAutoWaiting の4つの bool を _syncStateFlags の1つの int にまとめて同期([UdonSynced] フィールド数節約)

クールダウンの実装

  • _actionCooling フラグ + SendCustomEventDelayedSeconds(nameof(_ResetActionCool), actionInterval) の組み合わせで、Update ループなしに操作間隔を制御

遅延参加プレイヤーへのログ配信

  • _syncMessageLog を [UdonSynced] な string\n 区切り、8行分)として GameManager 側で保持・同期
  • SyncLogWindow 側は BehaviourSyncMode.NoVariableSync で自分では同期しない。GameManager.OnDeserialization から syncLogWindow.UpdateLog(_syncMessageLog) を呼ぶだけのプッシュ型設計
  • これにより後から入ったプレイヤーも OnDeserialization 受信時に最新ログが即反映される

World Space Canvas の Z-fighting 回避

  • Canvas_Log を Canvas_Main と同一平面に置くと GPU の深度判定が競合してちらつく

  • Canvas_Log の position.z に +0.001f(1mm)オフセットして回避

次回の予定

入力方式(再検討中)

  • トリガー入力 → 人差し指タッチ方式に変更を検討

  - VRCUiShape + OnPointerClick がトリガー不要で有力候補

  - InputHandler の入力受付部分を修正

VRChat UdonSharp Unity GameDev