Blueprintを作り込んでいくと、変数リストが PlayerName、PlayerHealth、PlayerAttack、PlayerIcon と増えていきます。関数に渡すたびに 4本のワイヤーを引く ことになり、引数を1つ足したくなったら、呼んでいる箇所を全部直すはめになります。
構造体(Struct) は、この「いつも一緒に扱う値」を 1つの型にまとめる 仕組みです。ワイヤーは1本になり、項目を足しても呼び出し側は無傷です。
ただし構造体には、Blueprintで ほぼ全員が一度は踏む罠 があります。 書き換えたのに反映されない という現象です。この記事では、構造体の作り方と使い方に加えて、この罠が起きる仕組みと直し方を解説します。
この記事でわかること
- 構造体は いつも一緒に扱う値 をまとめる型
- 取り出すのが Break 、組み立てるのが Make
- 値型 なので、Getで取り出すのは コピー 。ここが最大の罠
- 配列の中身を書き換え るには Set Array Elem か 参照で取得
- 実践:アイテムデータを設計して、書き換えられるようにする
いつ構造体にするか
判断はシンプルです。 いつも一緒に動く値が3つ以上あるかどうか 。

アイテムを例に考えてみます。「名前」「攻撃力」「価格」「アイコン」——これらは常にセットで扱われます。名前だけ渡して攻撃力を渡し忘れる、ということは起きません。 1つのモノを表している からです。
こうした値をバラバラの変数にしておくと、次の問題が出てきます。
- 関数の引数が増える: 4つの値を渡すのに、ワイヤーを4本引く
- 項目を足すと壊れる: 「レアリティ」を追加した瞬間、呼び出し箇所を全部直すことになる
- 配列にできない: 「アイテムを10個持つ」を表現するのに、4本の配列を並行管理する羽目になる
構造体にすると、これが 1本のワイヤー、1つの配列 になります。
| バラバラの変数 | 構造体 | |
|---|---|---|
| 関数に渡す | ワイヤー4本 | 1本 |
| 項目を追加 | 呼び出し側を全部修正 | 構造体を直すだけ |
| 複数持つ | 配列を4本並行管理 | 配列1本 |
配列との違い: 配列は 同じ型を並べる もの、構造体は 違う型をまとめる もの。「10個のアイテム」は配列、「1個のアイテムが持つ情報」は構造体です。両方を組み合わせて 「構造体の配列」 にするのが、インベントリの定番の形になります(実際に組む手順は インベントリシステムを作る で扱います)。
作り方とMake/Break
コンテンツブラウザで右クリック → Blueprints → Structure で作れます。名前は S_ を頭に付ける と、変数一覧で見分けやすくなります。
開いたら Add Variable で項目を足していきます。それぞれに型とデフォルト値を設定できます。
そして使うときのノードが2つです。

| ノード | 向き | 使う場面 |
|---|---|---|
| Make | 値 → 構造体 | 新しく1件作る(アイテムを生成する) |
| Break | 構造体 → 値 | 中身を取り出す(名前をUIに表示する) |
覚え方は 「Makeで作って、Breakで開ける」 。箱に詰めるのがMake、箱を開けるのがBreakです。
必要なピンだけ出せます。 構造体を繋いだピンを右クリック →
Split Struct Pinで、その場に中身を展開できます。また Make/Break ノードの詳細パネルでは、使わないピンを隠せます。10項目ある構造体でも、必要な2つだけ見えていればグラフはすっきりします。
最大の罠:値型のコピー
ここが本題です。 構造体は値型 で、この意味を理解しているかどうかで、詰まる時間が大きく変わります。

たとえば、インベントリ(構造体の配列)の1番目のアイテムの耐久値を減らしたいとします。素直に書くとこうなります。
Get(Inventory, Index 0) ← アイテムを取り出す
→ Break S_Item ← 中身を開ける
→ 耐久値から1を引く
→ Make S_Item ← 組み直す
そして、元の配列は1ミリも変わりません。
理由は、Get が返すのが コピーだから です。取り出した時点で別物になっているので、それをいくら書き換えても、配列の中身には影響しません。
直し方は2つあります。
方法1:書き戻す(Set Array Elem)
Get(Inventory, Index 0) → Break → 耐久値を減らす → Make
→ Set Array Elem(Target: Inventory, Index: 0, Item: 作り直した構造体) ← ★書き戻す
素直で分かりやすい方法です。 取り出す → 変える → 戻す の3手を必ずセットにします。
方法2:参照で取り出す
配列の Get ノードを 右クリック → Get a reference に切り替えると、コピーではなく 元への参照 が返ります。この場合は Set Members in Struct で直接書き換えられます。
なぜこんな仕様なのか。 値型はコピーが渡るぶん 安全 だからです。関数に渡した構造体を関数側が書き換えても、呼び出し元は影響を 受けません。この安全性と引き換えに、「書き換えたいときは明示的に書き戻す」必要があります。
症状の見分け方: 「値を変えるノードは通っているのに、次に見ると元に戻っている」——これが出たら、まずコピーを疑ってください。
変更するときの注意
もう1つ、実務で効いてくる注意点があります。 Blueprintの構造体は、あとから項目を変えると危ない 。

構造体にメンバーを追加・削除・並べ替えすると、 それを使っている場所の値がリセットされることがあります 。とくに危険なのが、DataTableに100件のデータを入れた後で構造体を変更するケースです。
対策は現実的なところで2つです。
- 設計を先に固める: DataTableに大量のデータを入れる前に、構造体の項目を決め切る。あとから足しそうな項目は、最初から入れておくほうが安全です
- 変更前にバックアップ: DataTableはCSVに書き出せます。構造体をいじる前にエクスポートしておけば、崩れても戻せます
C++で定義するという選択肢もあります。 構造体をC++側で持つと、この問題はかなり軽くなります。
USTRUCT(BlueprintType)
struct FItemData : public FTableRowBase
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadWrite)
FText DisplayName;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
int32 Attack = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
TObjectPtr<UTexture2D> Icon = nullptr;
};
USTRUCT(BlueprintType) を付けるとBlueprintから使えるようになり、FTableRowBase を継承するとDataTableの行として使えます。本格的にデータを持つなら C++側で定義する と覚えておくと、後々効いてきます(→ 最初のC++クラスを作る)。
実践:アイテムデータを設計する
RPGの装備、ローグライトの戦利品、サバイバルゲームのクラフト素材——「アイテムを持つ」仕組みはどのジャンルにも登場します。ここでは 構造体を作り、配列で持ち、中身を書き換える まで通してやります。
再現用の準備: 次を用意します。
| 種類 | 名前 | 内容 |
|---|---|---|
| Structure | S_Item | アイテム1件の情報 |
BP_Player の変数 | Inventory | S_Item 型の配列 |
ステップ1:構造体を作る。 右クリック → Blueprints → Structure 。S_Item と名付けて開き、次の項目を作ります。
| 変数名 | 型 | デフォルト値 |
|---|---|---|
DisplayName | Text | (空) |
Attack | Integer | 0 |
Durability | Integer | 100 |
デフォルト値を入れておくと、Make ノードで毎回入力しなくて済みます。 Durability を100にしておく のがポイントです。
ステップ2:配列として持つ。 BP_Player に変数 Inventory を作り、型を S_Item に。そして型の右にあるアイコンから Array(配列) に変更します。
ステップ3:アイテムを追加する。 BeginPlay で2件入れてみます。

Event BeginPlay
→ Make S_Item(DisplayName: "鉄の剣", Attack: 10, Durability: 100)
→ Add(Target: Inventory)
→ Make S_Item(DisplayName: "木の盾", Attack: 2, Durability: 50)
→ Add(Target: Inventory)
ステップ4:罠を体験する。 ここで、あえて 間違ったやり方 を試します。
Get(Inventory, Index 0) → Break S_Item
→ Subtract(A: Durability, B: 10)
→ Make S_Item(Durability にその結果、他はBreakの出力をそのまま)
→ Print String(作り直した構造体の Durability) ← 90 と出る
Print String には 90 が出ます。うまくいったように見えます。
ところが、その直後にもう一度配列から読み直してみてください。
Get(Inventory, Index 0) → Break S_Item
→ Print String(Durability) ← 100 のまま!
100のままです。 書き換えたのはコピーで、配列の中身は無傷でした。
ステップ5:正しく書き戻す。 Set Array Elem を追加して、関数の形にまとめます。

関数: DamageItem(入力: ItemIndex / Integer, Amount / Integer)
→ Get(Inventory, ItemIndex)
→ Break S_Item
→ Subtract(A: Durability, B: Amount)
→ Make S_Item(Durability にその結果、他はBreakの出力をそのまま)
→ Set Array Elem(Target: Inventory, Index: ItemIndex, Item: 作り直した構造体)
DamageItem(0, 10) を呼んでから配列を読み直すと、 今度は90になっています 。
Playして確認してください。 Set Array Elem を足す前は100のまま、足した後は90に変わります 。この差が体験できれば成功です。
うまくいかないときの切り分けです。
- やはり値が戻る →
Set Array ElemのIndexが、読み出したときと違っていないか確認 - 他の項目が消える → Breakの出力をMakeに繋ぎ忘れています。繋がなかった項目は既定値になります
- 構造体を変えたら値が消えた → メンバー変更の影響です。入れ直すか、CSVバックアップから戻します
ポイントは2つです。
- 取り出す・変える・戻す、の3手をセットで覚える: 構造体を配列やMapから取ってきて書き換えるときは、必ず書き戻しが要ります。 「Getしたものはコピー」 と覚えておけば、詰まったときに自力で気づけます
- 項目はできるだけ先に決める: あとからメンバーを足すと、入れたデータが飛ぶことがあります。「たぶん使う」項目は最初から入れておくほうが、結果的に安全です
アイテムが増えてきたら、Blueprintに直接書くのではなく 表で管理する 段階です。この S_Item はそのまま Data Table の行として使えます。1件ずつを独立したアセットとして持ちたいなら Data Assetでデータ駆動にする という選び方もあります。
おまけ:先に知っておくと良いこと
構造体の中に構造体を入れられます。 S_Item の中に S_Stats(攻撃・防御・素早さ)を持たせる、といった入れ子も可能です。ただし深くしすぎるとBreakが階層的になって読みづらいので、 2階層まで を目安にすると扱いやすくなります。
件数が多くて内容が固定なら、DataTableを先に考える。 「アイテムの一覧」のようなデータは、Blueprintで組み立てるよりDataTableに置くほうが管理しやすくなります。その場合、構造体は 行の形を定義する役割 になります。
Enumと組み合わせると分類ができます。 S_Item に ItemType(Enum: 武器 / 防具 / 消耗品)を持たせると、種類ごとの処理が書きやすくなります。ただし「炎属性かつ希少」のように 複数の性質を持たせたい なら、Enumより Gameplay Tags のほうが向いています。
関数の戻り値をまとめるのにも使えます。 出力ピンを複数持つ関数も作れますが、意味的にまとまった値なら構造体1つで返すほうが、呼び出し側がすっきりします。
状態を持たせるなら別の選択肢を。 構造体は値型なので、「常に最新の状態を共有したい」ものには向きません。HPのように複数から参照・更新される状態は、Componentにする ほうが素直です。
まとめ
構造体を使うときに押さえる点は、この4つです。
| 観点 | 結論 |
|---|---|
| いつ使うか | いつも一緒に扱う値が3つ以上 |
| 組み立て・分解 | Make で作り、 Break で開ける |
| 最大の注意 | 値型 。Getはコピーなので、書き戻さないと反映されない |
| 変更の注意 | メンバーを足すと 既存データが飛ぶことがある |
そして実務上の指針が1つあります。 Getしたものはコピー 。これさえ覚えておけば、「変えたはずなのに戻っている」で悩む時間がなくなります。
あなたのBlueprint、いつも4本まとめて引いているワイヤーはありませんか?