VRC Rogue 2026/05/16


概要

マルチプレイヤー同期が実機で動作確認済み。FlatBuffer8 に起因する [UdonSynced] クラッシュを根本解決し、2クライアント間でマップ・モンスター・アイテム・プレイヤー状態の同期が完了した。あわせて Python バランスシミュレーター(Rogue_simHTML)を整備し、パラメータ調整のワークフローを確立した。


変更点

ネットワーク同期

  • [UdonSynced] int[]string へ変換(DungeonGenerator)
    • VRChat FlatBuffer8 シリアライザが int[] を正しく処理できないため、モンスター・アイテムの全属性をビットパックし CSV 文字列(_syncPacked)1本で同期する方式に変更
    • フォーマット: "monCount,pos0,...,pos15,core0,...,core15,atkAlive0,...,atkAlive15,itemCount,item0,...,item11" — カンマ区切り 62 トークン
  • [UdonSynced] string 3本を削除(GameManager)
    • _syncWeaponName / _syncArmorName / _syncLastMessage が同様のクラッシュを引き起こしていたため削除
    • 武器・防具名はローカル変数として保持(observer への転送なし)
  • デバッグ切り分けフラグを解除
    • DEBUG_DISABLE_DUN_SERIALIZE / DEBUG_DISABLE_DUNGEON_SYNCtruefalse に変更
  • DungeonGenerator.asset の参照修復
    • sourceCsScript: {fileID: 0} になっていた参照を正しい GUID に修正

バランスシミュレーター(Rogue_simHTML

  • Python + Flask ベースのシミュレーターを新規作成
    • rogue_sim.py — シミュレーター本体 + Flask API サーバー
    • index.html — ブラウザ上で動作するダッシュボード UI
    • config.json — バランスパラメータ(UI から編集・保存可能)
  • Web UI 機能
    • 試行回数スライダー(100〜10,000)
    • Player / Food / Monster / Dungeon / Combat 各セクションのパラメータをリアルタイム編集
    • 変更値のオレンジハイライト表示
    • フロア別生存率グラフ(シアン/グリーン/オレンジ/レッドの4段階色分け)
    • 死因分布・武器分布・防具分布・フロア別死亡数チャート
    • SSE(Server-Sent Events)によるリアルタイム進捗表示
    • CSV エクスポート(summary / compare / floor / run の4セクション統合形式)
    • CONFIG SAVE / RESET ボタンで config.json へ永続化
  • CLI モード対応
    • python rogue_sim.py --cli -n 1000 で単体実行
    • --csv result.csv で統計 CSV を出力
  • LLM 連携テンプレート
    • PROMPT_TEMPLATE.md — シミュレーション結果をそのまま LLM へ渡す固定テンプレートを整備

バランス調整(config.json 現行値)

食料圧力を強化し、後半フロアでの死亡分散を狙ったパラメータに調整。

パラメータ変更内容
player.start_hp12 → 20(序盤安定化)
player.start_food100 → 80(食料圧力強化)
food.hunger_rate1 → 3(消費速度引き上げ)
food.food_heal_min/max40〜70 → 25〜45(食料の回復量を削減)
monster.atk_max3 → 4(中盤以降の脅威引き上げ)
monster.atk_floor_div2 → 3(ATK スケールをなだらかに)
exp_table全体的に引き上げ(レベルアップ速度の抑制)

修正

  • UdonIntArray.CreateUdonIntArray / Udon.CreateUdon クラッシュ
    • 原因: VRChat FlatBuffer8 シリアライザが [UdonSynced] int[] および [UdonSynced] string を正しく処理できない。内部的に値を sbyte として書き込もうとするため、範囲外でクラッシュする
    • 対応: int[] 4本を string _syncPacked(ビットパック CSV)1本に統合。string 3本は同期対象から外して削除
  • 同期が届かない(デバッグフラグ残留)
    • 原因: クラッシュ切り分けのために立てた DEBUG_DISABLE_DUN_SERIALIZE = true が残ったまま本番ビルドしていた
    • 対応: 両フラグを false に戻す

設計メモ

同期変数の制約(FlatBuffer8)

VRChat の現行シリアライザは [UdonSynced] に以下の制約がある。

可否
int / float / bool✅ 追加可能
int[] / string❌ FlatBuffer8 クラッシュ

武器・防具名など文字列を同期したい場合は、テーブルのインデックス(int)で同期し受信側でローカル解決するパターンを使う。

シミュレーターのゲームロジック再現仕様

プレイヤー攻撃ダメージ = max(1, rand(1, STR + atk_bonus) - monsterARM / def_divisor)
モンスター攻撃ダメージ = max(1, monsterATK - playerARM / def_divisor)
EXP報酬              = monsterMaxHP × 2

プレイヤー AI(シミュレーター内)は「HP 40% 未満でポーション即使用、フロア後にアイテム回収、上位装備のみ更新」という保守的ルールベース。実プレイヤーはより賢く動くため、実ゲームのクリア率はシミュレーターより高く出る想定。

バランス設計の方針

  • Win Rate の目標帯: 10〜25%(シミュレーター AI 基準)
  • 序盤(F1〜10)は生存率 90% 以上をキープし、入口ハードルを下げる
  • 中盤(F11〜18)で装備更新と食料管理のジレンマが生まれる設計
  • 終盤(F19〜26)が主な死のゾーン、ここで緊張感を出す

次に確認すること

  • シミュレーターで現行 config の Win Rate を計測し、目標帯(10〜25%)に収まっているか検証
  • 食料圧力強化後に「餓死」が死因として出現するか確認(food.hunger_rate=3 の効果測定)
  • 武器・防具の中間スペック(長剣・板金鎧)の採用率が低い場合、出現テーブルの調整を検討
  • デバッグログ([REBUILD][GENERATE][GM_POSTSER_OK] 等)の本番前削除
  • 同期後の observer 視点でのインゲーム動作をさらに検証(階段移動・フロア遷移)

vrchat udonsharp unity gamedev devlog