持ち物の「名前」「攻撃力」「耐久値」を別々の変数で管理していると、アイテムを渡すたびに3つの値を揃える必要があります。持ち物が増えると、「この名前と、この耐久値は同じ剣のものだろうか」と、対応を確かめる手間も増えてきます。
構造体(Struct) は、こうした情報をひとまとめにするための型です。「アイテム1個分の情報」を1本のワイヤーで渡せるようになります。
この記事では、鉄の剣のデータを作り、耐久値を100から90へ変えます。その途中で、手元のコピーは90なのに、持ち物の中身は100のまま になる場面も確かめます。どちらの値を変えたのかが分かれば、配列の更新で迷いにくくなります。
この記事でわかること
- 構造体に名前・攻撃力・耐久値をまとめる
- Makeで組み立て、Breakで必要な値を取り出す
- コピーと元の配列を読み比べ、書き戻した結果を確認する
Blueprintで変数を作り、ノードをつないだことがある人向けです。持ち物の画面は作らず、まずPrint Stringでデータの動きを確かめます。
構造体は1個分、配列は複数個分
構造体に入れる各項目を メンバー と呼びます。今回は「名前」「攻撃力」「耐久値」の3つです。まとめるかどうかは、項目数よりも、同じものの情報として一緒に扱いたいか を目安に考えます。
一方、配列(Array) は、同じ型の値を順番に並べて持つものです。構造体が「剣1本分の情報」なら、構造体の配列は「何本かの剣を並べた持ち物リスト」に当たります。

配列内の位置を表す番号が インデックス(Index) です。最初が0、次が1と、0から数えます。名前と耐久値を別々の配列に分ける方法もありますが、アイ テム1個を構造体にすると、その情報を同じ位置にまとめておけます。
構造体は、ゲーム内に剣を置く機能ではありません。まずは剣についての「情報」を扱います。見た目のActorを出す処理や、持ち物UIへ表示する処理は、その情報を受け取る側の仕事です。
構造体を作り、MakeとBreakを知る
練習用のフォルダで、コンテンツブラウザを右クリックし、「Blueprints」→「Structure」から S_DemoItem を作ります。S_ は構造体を見分けるための名前の付け方で、UEの必須ルールではありません。
開いたら「Add Variable」で項目を追加し、次の名前と型にします。型 は、その項目へ入れられる値の種類です。
| メンバー名 | 型 | 今回の意味 |
|---|---|---|
DisplayName | Text | 画面に表示するアイテム名 |
Attack | Integer | 攻撃力。整数で扱う |
Durability | Integer | 今の耐久値。整数で扱う |
「Default Values」で DisplayName を空、Attack を0、Durability を100にして保存します。デフォルト値 は、値を指定しなかったときの出発点です。すでに作った剣を、一斉に回復させる設定ではありません。
この型をBlueprintで使うと、次の2つのノードを作れます。
| ノード | すること | 鉄の剣の例 |
|---|---|---|
Make S_DemoItem | 各項目から構造体の値を組み立てる | 鉄の剣・10・100 → 1個分の情報 |
Break S_DemoItem | 構造体から各項目を取り出 す | 1個分の情報 → 名前、攻撃力、耐久値 |

Breakは「項目ごとに分けて読む」という意味です。アイテムを壊したり、配列から削除したりはしません。
MakeとBreakには白い実行ピンがありません。こうした 純粋ノード は、値を使う処理に必要になったときに評価されます。白い線で実行順をつなぐSetやPrint Stringと、役割が違います。
コピーを変えても、元の値は変わらない
構造体は、代入すると中の値がコピーされる 値型 です。今回の配列から取り出す Get (a copy) も、その位置にあるアイテムの情報をコピーして返します。
たとえば、持ち物にある鉄の剣の耐久値が100だとします。その情報を取り出して90へ変えても、変わったのは取り出した側です。元の配列を90にするには、変更後の情報を同じ位置へ入れ直します。

この「取り出す→変える→元の場所へ入れる」という最後の操作を、ここでは 書き戻し と呼びます。ファ イルへの保存ではなく、実行中の配列を更新する操作です。
配列には
Get (a ref)もあります。こちらの 参照 は、配列内の値そのものを扱うためのものです。「Getならすべてコピー」とは限りません。今回は違いを追いやすいGet (a copy)と、明示的な書き戻しで進めます。
実践:90と100の違いを確かめる
Playすると、コピーの耐久値90、元の配列の耐久値100を順に表示する実験を作ります。その後で書き戻しを追加し、配列を読み直した値が90になるところまで確かめます。
1. 練習用Actorに持ち物を用意する
親クラスがActorのBlueprint BP_StructPractice を作り、レベルへ1体だけ置きます。以降の変数とノードは、すべてこのBlueprintの中に作ります。
| 変数名 | 型 | 用途 |
|---|---|---|
Inventory | S_DemoItemのArray | 元の持ち物リスト |
WorkingItem | S_DemoItem(単一の値) | 変更後の情報を一時的に置く場所 |
変数の型で S_DemoItem を選び、Inventory だけコンテナの種類を「Array」にします。コンパイルしてから「Class Defaults」でInventoryを展開し、「+」で要素を1個追加します。
0番の中身を、DisplayName = 鉄の剣、Attack = 10、Durability = 100 にしてください。WorkingItemの初期値は後で上書きするので、そのままで構いません。
今回は、0番が存在する配列から始める ことが大切です。配列を空のままにすると、最初の読み取りでつまずきます。
2. 0番の情報を取り出す
Event GraphへInventoryをドラッグし、「Get」を選びます。これは配列全体を使うための変数ノードです。その出力から Get (a copy) を作り、位置の入力を0にします。さらに出力から Break S_DemoItem を作ります。

この3つは値を読み出す側です。まだ実行する処理につながっていないので、次に「読み出した値を、どこへ入れるか」を作ります。
3. 耐久値だけ90にして、WorkingItemへ入れる
Make S_DemoItem と Set WorkingItem を作ります。先ほどのBreakから DisplayName と Attack を、Makeの同じ名前の入力へつなぎます。Makeの Durability には90を直接入力します。

図のBreakは、直前に作ったものを続けて使います。ここでは減算の仕組みを増やさず、耐久値を90へ設定します。名前と攻撃力も渡しているのは、変更しない項目を保つため です。Makeの入力を空けると、元の剣の値を自動で引き継ぐわけではありません。
次にMakeの出力をSet WorkingItemへ、Event BeginPlay の白い実行出力をSet WorkingItemの実行入力へつなぎます。BeginPlayは、このActorがプレイを始めるときに呼ばれるイベントです。

図は同じグラフを分けて示しています。MakeやSet WorkingItemを図ごとに増やさず、前の接続へ続けてください。
4. コピーと元の配列を、それぞれ表示する
まずWorkingItemをGetし、Breakへ渡します。Breakの Durability を Print String の In String へドラッグしてつなぐと、整数を文字列に変える小さな変換ノードが入ります。図では To String (Integer) として描いています。
Print Stringは文字を表示するノード なので、整数90を表示するにも、この変換が必要です。Set WorkingItemの白い実行出力もPrint Stringへつなぎます。

こ の段階でコンパイルしてPlayすると、90が表示されます。停止して、次に元の配列を読む処理を続けます。
InventoryのGet→Get (a copy) の0番→Break→耐久値の文字列変換→2個目のPrint Stringを作ります。1個目のPrint Stringの実行出力を、2個目の実行入力につなぎます。

Playすると、1個目は90、2個目は100を表示します。画面上では新しいメッセージが上に並ぶことがあるため、上下の順番だけで判断せず、必要なら「Output Log」で出力順を確認してください。表示がすぐ消える場合は、各Print Stringの詳細ピンを開き、Duration を10にします。
WorkingItemに入れた90は、Inventoryの0番にはまだ入っていません。 Set WorkingItemまでの接続が失敗したのではなく、別の変数を更新した結果です。
5. 配列へ書き戻し、もう一度読む
2個目のPrint Stringの後へ、Set Array Elem を追加します。これは配列の指定した位置へ、値を入れるノードです。
| 入力 | つなぐもの・設定値 |
|---|---|
| 実行入力 | 2個目のPrint Stringの実行出力 |
Target Array | InventoryのGet |
Index | 0。取り出したときと同じ位置 |
Item | WorkingItemのGet |
Size to Fit | OFF |

Size to Fit は、指定位置が配列の外にあるときに配列を広げる設定です。今回はすでに存在する0番を置き換えるので、OFFにします。
最後に、手順4の「Inventoryから読み直してPrint Stringへ渡す」一組を複製し、3個目のPrint Stringを作ります。Set Array Elemの白い実行出力を、このPrint Stringの実行入力へつなぎます。最後の表示もWorkingItemではなく、Inventoryの0番から読みます。
最終的な白い実行線は、次の順です。
- Event BeginPlay → Set WorkingItem
- Print String:WorkingItemの耐久値を表示
- Print String:Inventoryの0番の耐久値を表示
- Set Array Elem:Inventoryの0番へ書き戻す
- Print String:Inventoryの0番を読み直して表示
コンパイルしてPlayし、出力順が 90→100→90 になれば成功です。最後が100のままなら、Set Array Elemの実行線、Target Array、Index、Itemを順に見ます。

今度はMakeの耐久値を70にしてみてください。結果は70→100→70になります。Playを停止して再開するたび、InventoryはClass Defaultsで指定した100から始まります。実行中の更新と、次の起動まで残すセーブは別の処理です。
ここまでできれば、「剣を使ったら耐久値を減らす」処理でも、元の値を読む→変更後の情報を作る→同じ位置へ戻す と考えられます。複数アイテムを扱うときは、読み取りと書き戻しに同じIndexを渡し、その位置が存在するか Is Valid Index で先に確かめます。
項目を増やすときの注意
今回の3項目なら、Makeへつなぐ線も多くありません。価格やアイコンを足していくと、耐久値だけを変えるのに、変更しない項目の線が増えていきます。
その場合は Set Members in Struct が役立ちます。今回の型では Set members in S_DemoItem という名前です。対象の構造体変数から作り、ノードのDetailsで Durability だけを入力として表示すれば、名前や攻撃力を保ったまま耐久値を変更できます。表示していないメンバーは変更されません。

ただし、WorkingItemを変更するなら、変更先はWorkingItemです。このノードを使っても、元のInventoryへ自動で書き戻されるわけではありません。先ほどの実験と同じように、変更する場所を確かめます。
また、剣1本の耐久値を変える操作と、S_DemoItem 自体へ項目を追加する操作は別です。後者は データの形を変える操作 なので、その型を使うBlueprintやData Tableにも確認が必要になります。
項目の削除や型の変更をする前は、プロジェクトをバージョン管理へ保存するか、バックアップを取ります。変更後は利用先をコンパイルし、未接続のピン、初期値、Data Tableの行を確認してください。CSVを書き出しておくのも補助になりますが、プロジェクト全体の代わりにはなりません。
おまけ:先に知っておくと良いこと
- 構造体にも「今の状態」を入れられる:今回の耐久値がその例です。プレイヤーやUIが別々に正しい値を持とうとするより、Inventoryを管理するActorやComponentを決め、その場所の値を更新すると追いやすくなります。
- 種類の設定と、持っている1個の状態を分ける:鉄の剣の基本攻撃力は種類ごとの設定、使い込んだ1本の残り耐久値は所持品ごとの状態です。種類が増えたら、Data TableやData Assetで共通設定を管理する方法へ進めます。
- 構造体をコピーしても、Actorが増えるわけではない:構造体の中にActorなどのObject参照があれば、コピー側の参照も同じObjectを指します。今回のTextとIntegerの例から、「中に入れたものすべてが別個に複製される」とは考えないようにします。
まとめ
構造体は、名前・攻撃力・耐久値を「アイテム1個分」として扱うための型です。Makeで組み立て、Breakで必要な項目を読みます。
配列の更新で迷ったら、いま変えたのはコピーか、元の配列か を確かめてください。今回の90→100→90という出力は、その違いを目で追うための小さな実験です。
次はこのデータに「拾う」「使う」といった操作とUIを加えると、インベントリシステムにつながります。