7.

UE5でアクターからレベルの変数にアクセスする方法|GameState・Dispatcher活用

編集

UE5でアクタからレベルブループリント(レベルBP)の変数へ直接アクセスすることは、基本的にできません。レベルBPは他のブループリントから参照やキャストの対象にできない特別な存在のため、値をやり取りしたい場合は「レベルBPからアクタへ働きかける」か、「GameStateGameInstanceなど共有できる場所に値を置く」という二段構えで設計するのが定石です。この記事では、その理由と具体的な実現手段、選び方の指針、そしてよくある落とし穴までを整理して解説します。

この記事の要点
  • レベルBPは外部のブループリントから直接参照・キャストできないため、アクタから「レベルBPの変数」を直接読むことは前提としてできない。
  • 「レベルBP→アクタ」の向きなら、レベルBP側でアクタ参照を取得し、そのアクタのイベントや変数を操作するのが基本。
  • 「アクタ→レベル全体の値」がほしい場合は、GameState・GameInstanceなど共有可能な場所に値を置くのが定石。
  • 変化を双方向に伝えたいときは Event Dispatcher(イベントディスパッチャ) による通知が有効。
  • レベルBPに状態を持たせすぎる設計は、保守性・再利用性・レベル遷移時のデータ保持の面で不利になりやすい。

1. なぜレベルBPの変数は外から直接見えないのか

UE5では、ワールド(マップ)ごとに レベルブループリント が1つ存在し、そのレベル専用の処理や変数を持てます。一見すると便利ですが、レベルBPは通常のアクタ・コンポーネントとは性質が異なり、他のブループリントからインスタンスとして参照・キャストする手段が用意されていません

通常のアクタ同士であれば、相手のアクタ参照(オブジェクト参照)さえ得られれば、その変数を「Get」ノードで読んだりイベントを呼んだりできます。しかしレベルBPは、スポーン(生成)したり「Cast To」で取得したりする対象にできないため、同じ要領でアクセスできません。これがUE5を学び始めた人がつまずきやすい代表的なポイントです。

したがって、設計の出発点は「レベルBPの変数を外から読む方法を探す」ことではなく、そもそも値をどこに置くべきかを考えることになります。以降で2つの方向性を順に見ていきます。

2. 方法①:レベルBP→アクタの向きで操作する

レベルBPは「アクタを参照する側」にはなれます。つまり、レベルBPからレベル内に配置済みのアクタへ働きかける向きであれば、特別な仕組みは不要です。レベルBP側で状態が変わったタイミングに、対象アクタへ値を渡したりイベントを呼んだりすればよいのです。

典型的な手順は次のとおりです。

  1. レベル上に対象のアクタを配置しておく。
  2. そのアクタを選択した状態で、レベルBPのグラフ上で右クリックし、「選択中のアクタへの参照を作成(Create a Reference to ...)」を選ぶ。これでレベルBP内にアクタ参照ノードが置かれる。
  3. そのアクタ参照から、対象アクタが 公開している変数(Instance Editable/公開設定が有効な変数)への「Set」ノードや、対象アクタに定義した カスタムイベント を呼び出す。

この向きであれば、レベルBPが持っている情報をアクタへ「押し出す(プッシュする)」形で確実に伝えられます。レベル固有の演出トリガーや、そのレベルにしか存在しないアクタの初期化などに向いています。

// レベルBP側のイメージ(向き:レベルBP → アクタ)

[BeginPlay/任意のトリガー]

 └→ [対象アクタへの参照]── Set 公開変数 ─→ [対象アクタのカスタムイベント を Call]

注意点として、ここでアクタ側に置く変数は、外部から書き換えられるよう 公開(目のアイコンを開く/Instance Editable) にしておく必要があります。レベルBPが直接見られるのは「アクタの変数」であって、「レベルBP自身の変数」ではない、という対象の違いを意識すると混乱しにくくなります。

3. 方法②:アクタ→レベルの値は共有場所に置く

逆に「アクタ側から、いま開いているレベル全体に関わる値を読みたい・書きたい」という場合は、レベルBPに値を持たせるのではなく、複数のブループリントから安全に参照できる共有の置き場所に値を移すのが定石です。代表的な置き場所は次の3つです。

3-1. GameState

GameState は、そのレベル(ワールド)全体で共有したい状態を保持するのに適したクラスです。例えば「現在のスコア」「クリア済みの目標」「進行フェーズ」など、レベル内のどのアクタからも知りたい値を置く場所として標準的に使われます。任意のアクタから「Get Game State」相当のノードで取得し、自作のGameStateクラスへ Cast To してから変数へアクセスします。なお、GameStateはレベルを切り替えると基本的に作り直されるため、レベルをまたいで保持したいデータには向きません。

3-2. GameInstance

GameInstance は、ゲーム起動中はレベルを切り替えても破棄されずに残る数少ない存在です。そのため、レベル遷移をまたいで持ち越したい値(プレイヤーの所持品、選択した難易度、進行中のセーブ用データなど)を置くのに適しています。どのレベルからでも「Get Game Instance」相当のノードで取得し、自作クラスへキャストして使います。

3-3. GameMode

GameMode は、そのレベルでのルールや進行を管理するクラスです(マルチプレイではサーバ側にのみ存在する点に注意)。レベルごとに割り当てを変えられるため、レベル固有のルールや設定値の置き場所として使えます。クライアントからも参照したい共有状態は、GameModeよりGameStateに置くほうが適しています。

// アクタ側のイメージ(向き:アクタ → 共有場所)

[Get Game State]── Cast To BP_MyGameState ──→ [Get 共有変数]

               └ Cast Failed の場合はアクセスしない(後述の落とし穴を参照)

4. 方法③:Event Dispatcherで変化を通知する

共有場所に値を置いたうえで、「値が変わった瞬間」を他のブループリントへ知らせたい場合は、Event Dispatcher(イベントディスパッチャ) が有効です。値を保持する側(例:GameState)でディスパッチャを定義し、値が変化したタイミングで Call します。通知を受け取りたい側のアクタは、そのディスパッチャに対して Bind Event しておくことで、変化に合わせて自分の処理を実行できます。

これにより、各アクタが毎フレーム値を監視(ポーリング)する必要がなくなり、必要なときだけ反応する効率的で疎結合な構成にできます。レベルBPから何かを伝えたい場合も、レベルBPでディスパッチャをCallし、アクタ側でBindしておく、という形にすれば、向きを問わず通知を流せます。

5. 手段の比較

手段主な向きレベル遷移で保持向いている用途推奨度
レベルBPの変数を直接参照(外部からは不可)不可
レベルBP→アクタ参照で操作レベルBP→アクタ消えるレベル固有アクタの初期化・演出トリガー用途次第
GameStateアクタ⇄共有消えるレベル内で全アクタが共有する状態推奨
GameInstanceアクタ⇄共有保持されるレベルをまたぐ持ち越しデータ推奨
GameModeアクタ⇄共有消えるレベル固有のルール・設定用途次第
Event Dispatcher双方向の通知値の変化を疎結合に伝える推奨

大まかな指針として、共有したい状態はGameStateかGameInstanceに置き、変化の通知はEvent Dispatcherで行うのが扱いやすい構成です。レベル遷移をまたぐかどうかで、GameState(またぐと消える)とGameInstance(残る)を使い分けます。

6. 落とし穴

つまずきやすいポイント
  • レベルBPの変数を外から読もうとする: レベルBPは参照・キャストの対象にできないため、この前提自体を見直す必要がある。値はGameStateなどへ移す。
  • レベルBPに状態を持たせすぎる: レベルBPはそのマップ専用で再利用が利かず、肥大化すると保守が難しくなる。ロジックや状態は再利用可能なアクタ・コンポーネント・GameStateへ寄せるとよい。
  • レベル遷移でデータが消える: レベルBPやGameStateに置いた値は、別レベルをロードすると基本的に作り直される。持ち越したい値はGameInstanceやセーブデータに置く。
  • キャスト失敗の未処理: 「Get Game State」などで取得した参照を自作クラスへCastする際、想定外のクラスだとCastが失敗してNullになる。Cast Failedの経路を用意し、Null参照のままアクセスしないようにする。
  • マルチプレイでの不整合: GameModeはサーバ側にのみ存在し、各クライアントには無い。クライアントからも見たい共有状態はGameStateに置き、複製(レプリケーション)の設計も合わせて検討する。

7. よくある質問(FAQ)

Q1. アクタから「Get Level Blueprint」のようなノードでレベルBPを取得して変数を読めますか?

いいえ、そうした使い方は想定されていません。レベルBPは他のブループリントからインスタンスとして取得・キャストする対象にできないため、変数を直接読むことはできません。共有したい値はGameStateやGameInstanceへ移し、そちらを経由して読み書きするのが正しいアプローチです。

Q2. レベルBPで管理していたフラグを、複数のアクタから読み書きしたい場合はどうすればよいですか?

そのフラグをGameState(レベルをまたがない場合)またはGameInstance(またぐ場合)の変数として定義し直すのがおすすめです。各アクタは共有場所から値を読み書きし、変化をほかへ伝えたいときはEvent Dispatcherで通知します。こうするとレベルBPへの依存がなくなり、再利用性とテストのしやすさが向上します。

Q3. GameStateとGameInstanceは、どちらを使えばよいか迷います。

判断の軸は「レベルを切り替えたあとも値を残したいか」です。残したいならGameInstance、そのレベル内だけで完結してよいならGameStateが基本です。スコアのようにレベルごとにリセットされてよい値はGameState、所持品や進行状況のように持ち越したい値はGameInstance、と考えると整理しやすいでしょう。具体的な挙動はプロジェクトの構成やエンジンのバージョンによって細部が異なる場合があるため、最終的には公式ドキュメントで確認することをおすすめします。

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. レベルを移動する方法
  2. レベルの「基本」テンプレートと「オープンワールド」テンプレートの違い
  3. Blueprintで現在開いているレベルが特定のレベルであるか調べる方法
  4. レベルごとにゲームモードを変更する方法
  5. 動的にインスタンスが属するレベルを変更する方法
  6. エディタ上でインスタンスが属するサブレベルを変更する方法
  7. とあるアクタから現在開いているレベルの変数にアクセスする方法
  8. プロジェクトを開いたときの最初のレベルを変更する方法

最近更新/作成されたページ