Blueprintを作り込んでいくと、Variablesパネルが変数でぎっしり埋まり、どれが大事な変数なのか分からなくなります。原因はたいてい、 一時的な計算結果まで全部Class Variableで作ってしまう ことです。
UEのBlueprintには、寿命と届く範囲が違う2種類の変数、Class VariableとLocal Variableがあります。使い分けの軸はたった1つ、 「状態か、途中計算か」 です。この記事では、2つの変数の違いと、「関数を2回呼んだら値が2倍になる」バグをわざと起こして直す手順を解説します。
この記事でわかること
- 2種類の変数の違いは 「スコープ(届く範囲)」と「寿命」
- 使い分けの軸は 「状態はClass、途中計算はLocal」
- Local Variableは Function内でのみ 作れる(イベントグラフでは不可)
- 実践:ループの累積で 「2回呼ぶと2倍」バグ をわざと起こして直す
2種類の変数:スコープと寿命の違い
Blueprintの変数は、作る場所によって性質がまったく変わります。
- Class Variables(クラス変数/メンバ変数): My Blueprintパネルの「Variables」セクションで作る、いつもの変数
- Local Variables(ローカル変数): Function(関数)の中でだけ 作れる変数。関数を開いているときだけ、My Blueprintパネルに「Local Variables」セクションが現れます
違いは2つの軸で整理できます。1つ目は スコープ(どこから届くか) 。

| Class Variable | Local Variable | |
|---|---|---|
| スコープ | Blueprint内のすべての関数・イベントから読み書き可(Public設定なら外部からも) | 定義した関数の中だけ。外からは一切見えない |
| 寿命 | インスタンスの生成から破棄まで | 関数の開始から終了まで |
| 主な用途 | オブジェクトの 状態 ・設定値・参照 | 一時的な 計算結果 ・中間データ |
2つ目は 寿命(いつまで生きるか) です。

Class Variableはアクターが生きている限り値を持ち続けます。一方のLocal Variableは関数が呼ばれた瞬間に生まれ、関数が終わると跡形もなく消えます。この「すぐ消える」性質が、後述するバグ予防の要になります。
重要な補足: Local VariableはFunction内でのみ定義できます。 イベントグラフでは作れません 。イベントグラフで一時的な値を持ちたくなったら、それは処理をFunctionに切り出すサインです(→ FunctionとMacroの違い)。
使い分けの原則:状態はClass、途中計算はLocal
判断の原則は 「スコープの最小化」 です。変数が届く範囲は、狭ければ狭いほど安全になります。

Class Variableにすべきもの:オブジェクトの「状態」
プレイヤーの CurrentHP・MaxHP・IsDead を考えてみてください。ダメージイベントで減り、回復関数で増え、UI更新から読まれる——つまり 複数の処理から参照・更新される「いまの状態」 です。これはClass Variableの出番です。
Event ReceiveDamage
→ CurrentHP(Class Variable)から Damage を引いて Set
→ CurrentHP <= 0 なら → IsDead(Class Variable)を True に Set
Local Variableにすべきもの:関数内で完結する「途中計算」
一方、ダメージ計算関数の中で使う「基礎ダメージ×バフ倍率の中間結果」はどうでしょう。この値が必要なのは、計算している 数ミリ秒の間だけ です。関数の外の誰も、この値を知る必要がありません。これがLocal Variableの出番です。
Function: CalculateFinalDamage(Return Value: Float)
→ BaseDamage × BuffMultiplier の結果を Local Variable: IntermediateDamage に Set
→ IntermediateDamage × CriticalMultiplier を Return Value として返す
関数が終われば IntermediateDamage は消え去り、Variablesパネルを汚すことも、他の処理に影響することもありません。
全部Class Variableにすると何が起きるか
初心者が最も踏みやすい地雷が、「一時的な計算結果まで全部Class Variableにする」ことです。起きる問題は、大きく3つあります。
- 変数リストの肥大化: 本当に大事な状態変数が、使い捨ての変数の山に埋もれます
- デバッグの迷宮化: どこからでも書き換えられる変数は、「なぜこの値が変わったんだ?」の容疑者が全処理になります。Local Variableなら容疑者はその関数の中だけなので、捜査範囲が一気に絞れます(→ Print Stringデバッグ手法)
- 値の残留バグ: 最大の罠がこれです。Class Variableは 前回の値を覚えています 。次の実践で、実際に踏んでみましょう
実践:「2回呼ぶと2倍」バグをわざと起こして直す
RPGの合計スコア、シューティングのコンボ集計、インベントリの合計重量——「配列をループで回して合計する」処理はどのジャンルにも登場します。そしてこの処理は、変数の選び方を間違えたときの症状がいちばん分かりやすい教材でもあります。今回は わざと間違えて、バグを目撃してから直します 。

再現用の準備。適当なActor Blueprint(BP_ScoreTester など)に、次の変数を用意します。
| 変数名 | 型 | 初期値 | 置き場所 |
|---|---|---|---|
ScoreArray | Integer配列 | 100, 100, 100 | Variablesパネル(Class Variable) |
TotalScore | Integer | 0 | Variablesパネル(=これがわざと間違えた置き場所) |
-
わざと間違えた関数を作る: Function
CalculateTotalScore(戻り値: Total / Integer)を作り、中身をこう組みますFunction: CalculateTotalScore(戻り値: Total / Integer) → For Each Loop(Array: ScoreArray) Loop Body → Set TotalScore(= Add(A: TotalScore, B: Array Element)) Completed → Return Node(Total ← TotalScore) -
2回呼んで観察する: イベントグラフで、続けて2回呼びます
Event BeginPlay → CalculateTotalScore → Print String(Append("1回目: ", ToString(Total))) → CalculateTotalScore → Print String(Append("2回目: ", ToString(Total)))Playすると、
1回目: 300と表示されます。正解です。ところが2回目: 600。配列は1つも変わっていないのに、合計が2倍になりました -
犯人を言葉にする:
TotalScoreはClass Variableなので、1回目の300が 関数が終わっても生き残り 、2回目の加算がその上に積まれました -
直す:
TotalScoreをVariablesパネルから 削除 し、CalculateTotalScoreを開いた状態でMy Blueprintパネルの Local Variables にRunningTotal(Integer)を作り直します。中身は置き換えるだけですFunction: CalculateTotalScore(戻り値: Total / Integer) → For Each Loop(Array: ScoreArray) Loop Body → Set RunningTotal(= Add(A: RunningTotal, B: Array Element)) ← Localに変更 Completed → Return Node(Total ← RunningTotal)Playすると、
1回目: 300/2回目: 300。何回呼んでも300です。Local Variableは呼び出しのたびに まっさらな0か ら 始まるからですグラフとして変わったのは、変数の置き場所だけです。それだけで結果が変わります。


「初期化ノードを足せばClass Variableでも直るのでは?」と思った方もいるはずです。そのとおりで、関数の先頭で0をSetすれば動きます。ただしそれは、「毎回リセットが必要な変数」を自分で管理し続けるということでもあります。 Local Variableなら、リセットは仕組みの側が保証してくれます 。人間の注意力より仕組みに頼るのが、バグの少ないBlueprintへの近道です。
ポイントは2つです。
- 「関数が終わった後もこの値は必要か?」と自問する: Noなら迷わずLocal。この一問だけで変数の9割は正しく仕分けられます
- 症状から犯人を推理できるようになる: 「2回目から値がおかしい」「リトライしたら前回の状態が残っていた」——この症状を見たら、Class Variableの残留をまず疑う。この嗅覚は 今後ずっと役立ちます
おまけ:先に知っておくと良いこと
- 関数のInput/Outputピンも仲間: 関数に値を渡すならInputピン、返すならReturnノードを使います。「引数と戻り値で受け渡す」形は、Local Variableすら不要になる最もクリーンな書き方です。Local Variableは「関数の中で何度も使い回す中間値」に絞ると美しく収まります
- Class Variableには整理機能がある: 変数が増えてきたら、詳細パネルの Category でグループ分けできます。
Stats・Configのように分類しておくと、Variablesパネルが読みやすくなります - インスタンスごとに値を変えたいなら: Class Variableの Instance Editable をONにすると、レベルに置いた個体ごとに詳細パネルで値を変えられます。「同じ敵Blueprintで、この個体だけHPを高く」が実現できます
まとめ:変数選択のチェックリスト
| 質問 | YESなら |
|---|---|
| オブジェクトの状態・設定を保持する?(HP、フラグ、参照) | Class Variable |
| 複数の関数・イベントから参照される? | Class Variable |
| 処理が終わった後も値が必要? | Class Variable |
| 1つの関数の中だけで使う一時データ? | Local Variable |
| 処理が終わったら捨てて良い? | Local Variable |
合言葉は 「状 態(ステート)はClass Variable、過程(プロセス)はLocal Variable」 。変数を1つ作るたびにこの仕分けを意識するだけで、Blueprintの読みやすさとバグ耐性は目に見えて変わります。
変数の次は、処理のまとめ方です。FunctionとMacroの違いで「処理を関数に切り出す」技術を、Blueprintグラフを整理する10のテクニックでグラフ全体の整頓術を身につけましょう。
あなたのBlueprintのVariablesパネルを、今スクロールしてみてください。「関数が終わったら要らない値」が、何個まぎれていますか?