[DevLog #001]UE5 + FCS: 安全なダンジョン遷移のためのUIと通信の完全同期設計

DevLog

1. 今回の実装目的と解決した課題

Flexible Combat System (FCS) の設計思想に基づき、ダンジョン入口UIからの「出発ボタン」押下によるダンジョン生成と、全プレイヤーのワープ・暗転処理を同期させるシステムを構築しました。
ホストとクライアント間でのUI表示の残りや、座標同期の失敗による「座標の巻き戻し」が発生しましたが、今回はFCSのUI管理ルールに従いつつ、信頼性の高い「ハンドシェイク(同期)」処理を実現しました。

2. 開発の背景と設計思想 (Why & How)

FCS環境で最も注意すべきは「循環参照によるエディタの破損」「通信の確実性」です。

  • 循環参照の回避: UIクラスをPCで直接保持せず、User Widget(親クラス)として保持することで、ビルド時や起動時のインターフェース破損を防ぎます。
  • 責務分離の徹底: UIはインターフェース経由でPC(Controller)に依頼を投げるだけで、直接PCのロジックを叩かない設計にしました。
  • 通信の信頼性: 座標更新には SetActorLocation を直接使わず、Reliable RPC を介した強制テレポートを採用しました。

3. 実装と修正の詳細 (Technical Diff)

  • BP_PlayerController
  • 対象の関数/イベント: CreateWidgets, IsWidgetOpen, Event ToggleDungeonEntranceUI, Server_RequestStartDungeon, Client_ExecuteWarp
  • 追加・変更した変数: WBP_DungeonEntrance_Ref (User Widget型)
  • 実装内容:
    • WBP_DungeonEntrance を事前生成し、汎用的な User Widget 型で保持する。特定のUIクラス(WBP_DungeonEntrance)で変数を保持すると、PCとUIの間で循環参照が起き、エディタ起動時にインターフェースが破損するため、必ず汎用の親クラス(User Widget)で保持する。
    • Client_ExecuteWarp (Run On Owning Client / Reliable) を実装し、サーバーからの強制ワープを実行。bTeleport = True を使用して物理補正を無効化。
WBP_DungeonEntranceのブループリントの画像
 BP_PlayerController のサーバー・クライアント間RPCノード構成の画像
  • BP_MyGameState
  • 対象の関数/イベント: Server_RequestNextFloor, Server_OnPlayerFinishedBuilding, Server_CompleteDungeonGeneration
  • 追加した変数: ReadyPlayersCount (Int), BuildTimeoutHandle (Timer Handle)
  • 実装内容:
    • ReadyPlayersCount で完了報告をカウントし、全員揃った瞬間にワープと暗転解除を命令。
    • フリーズ対策として10秒のタイムアウトタイマーを実装。
クライアントからの「生成完了」報告を受け取るカウンターを実装しているブループリントの画像
Server_CompleteDungeonGenerationの全員分の生成が完了(またはタイムアウト)した時に呼ばれる最終処理
  • WBP_DungeonEntrance (UI)
  • 対象の関数/イベント: Btn_Depart_OnClicked, SetGamepadFocus
  • 実装内容:
    • ボタン押下時にインターフェース経由でPCへ依頼。
    • 画面表示直後に0.05秒のDelayを挟み SetFocus することで、ゲームパッドでの決定ボタン操作に対応。

4. トラブルシューティング

  • 不具合: クライアントがロード中に暗転が戻らない。
  • 解決策: ウィジェットの多重生成が起こっていたため、ToggleLoadingScreenIs Valid チェックを追加し、ウィジェットの多重生成を阻止。また、Run Phase の変更直後に Delay (0.5s) を入れ、1フレーム通信による状態変化の取りこぼしを物理的に回避しました。

5. 未来の自分へ:次回実装時のテンプレート(標準手順)

新しいUIを追加する際の標準フローを定義しました。

5-1. E_WidgetUI(Enum)

  • 追加: Enum要素 DungeonEntrance
  • 目的: IsWidgetOpen / ToggleWidgets が扱うUI識別子への追加。

5-2. I_PlayerController(Interface)

  • 追加関数: ToggleDungeonEntranceUI, RequestDungeonStart_Interface
  • 目的: FCS標準のUI管理フローへの準拠と、UIとPCの疎結合化。

5-3. BP_PlayerController(最重要実装)

  • 変数: WBP_DungeonEntrance_Ref (Object Reference: User Widget)
    • ※汎用親クラス保持により、特定のWidgetクラスとの循環参照を回避。
  • 関数: CreateWidgets:
    • 事前生成し、FCS既存の WidgetList 処理や Collapsed 設定の「前段」で登録を実行。
  • 関数: Is Widget Open: DungeonEntrance 分岐を追加。
  • イベント: ToggleDungeonEntranceUI: FCS標準テンプレ(Adjust Input Mode → ToggleWidgets)で実装。
  • RPCの実装:
    • Server_RequestStartDungeon (Run On Server / Reliable): サーバーへ開始要求を送信。
    • Client_ExecuteWarp (Run On Owning Client / Reliable): 強制テレポート。bTeleport = True で物理補正を無効化。
    • Server_NotifyDungeonBuilt (Run On Server / Reliable): クライアントの地形生成完了報告。
  • 暗転ロード運用ルール:
    • クライアント自律型の RunPhase (RepNotify) 管理。
    • Listen Server(ホスト)は自身の OnRep が発火しないため、サーバー処理直後に手動で暗転を制御。
    • ToggleLoadingScreen 内で Is Valid チェックを徹底し、暗転の多重生成を阻止。

5-4. BP_PlayerCharacter(Interact)

  • Interact処理: 既存の Combat Interact 前段に IsValid(CurrentEntrance) を追加。該当時のみ ToggleDungeonEntranceUI を実行。

5-5. BP_DungeonEntrance

  • UI生成責務を削除。すべてPlayerControllerへ集約。

5-6. WBP_DungeonEntrance(UI)

  • Btn_Depart (OnClicked): 「UIを閉じる」→「Interface依頼送信」の順序を厳守
  • Gamepad対応: 表示直後に0.05秒のDelayを挟み SetFocus。

5-7. BP_MyGameState

  • サーバー制御: Server_RequestNextFloor はNot Replicatedに変更し、制御を BP_PlayerController に集約。
  • ハンドシェイク変数: ReadyPlayersCount (カウント用), BuildTimeoutHandle (15秒タイムアウト用)。

🇺🇸 [English Version]

※ English version below.
※ The English text is AI-translated from the original Japanese article.

🇺🇸 [English Version]UE5 + FCS: Implementing Robust UI and Synchronized Dungeon Transitions

1. Objective and Problem Solved

We have built a dungeon transition system compliant with the Flexible Combat System (FCS) architecture. The goal was to ensure synchronized dungeon generation, player warping, and screen fading across all clients when a “Depart” button is clicked. We addressed issues such as lingering UI elements and coordinate synchronization failures (rubber-banding) by implementing a robust handshake mechanism.

2. Design Philosophy (Why & How)

The key focus in an FCS environment is avoiding “Circular References” and ensuring “Communication Reliability.”

  • Avoiding Circular References: We hold UI references as User Widget (base class) rather than specific types within the PlayerController to prevent editor crashes/interface corruption.
  • Strict MVC: UI (View) communicates with the PlayerController (Controller) solely through interfaces, maintaining loose coupling.
  • Reliable Communication: We implemented Reliable RPCs for teleportation, ensuring packets are received and ignoring physics displacement during warp.

3. Implementation Details (Technical Diff) [DO NOT SUMMARIZE]

  • BP_PlayerController
  • Target Function/Event: CreateWidgets, IsWidgetOpen, Server_RequestStartDungeon, Client_ExecuteWarp
  • Variables Added/Modified: WBP_DungeonEntrance_Ref (User Widget Object Reference)
  • Details:
    • Pre-generated the widget and stored it as a generic User Widget to avoid circular references.
    • Implemented Client_ExecuteWarp (Run On Owning Client / Reliable) to execute force-teleportation on clients, using bTeleport = True to bypass physics interference.

📸 [Insert image of BP_PlayerController RPC setup here]

  • BP_MyGameState
  • Target Function/Event: Server_RequestNextFloor, Server_OnPlayerFinishedBuilding, Server_CompleteDungeonGeneration
  • Variables Added/Modified: ReadyPlayersCount (Integer), BuildTimeoutHandle (Timer Handle)
  • Details:
    • Managed completion reports via ReadyPlayersCount. Triggered warp and screen clear only when all clients report success.
    • Implemented a 15-second timeout fail-safe to handle player freezes.

📸 [Insert image of Server_CompleteDungeonGeneration and Timer Control here]

  • WBP_DungeonEntrance (UI)
  • Target Function/Event: Btn_Depart_OnClicked, SetGamepadFocus
  • Details:
    • Emitted interface requests to PC upon button click.
    • Implemented a slight Delay (0.05s) before SetFocus upon UI display to ensure gamepad compatibility.

4. Troubleshooting

  • Issue: Clients stuck in black screen due to failure in screen fade toggle, or multi-generation freezes.
  • Fix: Added Is Valid checks to ToggleLoadingScreen to prevent multiple overlapping widgets. Inserted a Delay (0.5s) immediately after changing Run Phase to prevent “1-frame communication loss” where state changes are ignored by clients.

5. Template for Future Implementation

Follow this standard flow for adding new UI within the FCS framework:

  1. Enum: Add to E_WidgetUI.
  2. PC Interface: Register ToggleYourWidgetUI in I_PlayerController.
  3. Pre-generation: Generate in CreateWidgets using User Widget type.
  4. Check: Add branching logic in IsWidgetOpen.
  5. Toggle: Use standard FCS toggle event pattern.
  6. Focus: Implement micro-delay + SetFocus for gamepad support.
  7. Request: UI button clicks must only use Interface messages (No direct casting to PC).
タイトルとURLをコピーしました