【Unreal Engine】インスタンシング入門:同じ小物をISMでまとめて、描画の負荷を減らす

作成: 2026-07-25最終更新: 2026-09-07

同じ岩や柱を大量に置くときに使うISMを図解。配置済みActorをBatchでまとめて比較し、BlueprintのAdd Instanceで柱を並べます。ISM・HISM・Foliage、削除後の番号、距離カリング、Naniteとの関係も解説します。

遺跡の柱、道沿いの柵、草原の岩。同じ小物を増やすと景色は豊かになりますが、その一つひとつを別のActorとして扱う負荷も増えていきます。

ここで試したいのが インスタンシング です。「同じ形を、これらの位置に置く」とまとめて扱うことで、見た目の数を保ちながら、描画の準備や配置物の管理を軽くできる場合があります。

同じ本数の柱を、個別のActorと一つのISMコンポーネントで扱う違い

UEでは Instanced Static Mesh(ISM) コンポーネントを使います。この記事では、配置済みの小物をまとめて比べる方法から始め、後半ではBlueprintで柱を一本、次に八本並べてみます。

この記事でわかること

  • 描画命令の回数と、stat unit のDrawの時間の違い
  • ISMで共有するものと、配置ごとに変えられるもの
  • 配置済みActorの変換と、Add Instanceで増やす手順
  • ISM・HISM・Foliageの選び方、削除と距離設定の注意

Windows版UE5で、Actorの配置とBlueprintの基本操作を経験した方を想定します。外部アセットは使わず、Engineの基本形状を練習用にコピーします。掲載図はブログ用の模式図で、Blueprint図は接続を再現するために使います。

Sponsored

ISMは、同じ形と個々の配置をまとめて持つ

ISMの インスタンス は、同じメッシュを使う一個分の配置です。メッシュは立体モデルの形を表すデータで、ISMではその形やマテリアルを共有します。一方、どこへ置き、どちらへ向け、どの大きさにするかは、それぞれ変えられます。

この 位置・回転・スケールを一組にした情報 が、Transform です。ISMは「共通の形」と「個々のTransform」を持つ、と考えると分かりやすくなります。

ISMは一つのメッシュを共有し、それぞれの位置・回転・スケールを持つ

たとえば同じ柱が32本あっても、32個のActorを作る代わりに、一個のActorへISMコンポーネントを付けて32個の配置を持たせられます。形を共有しながら、一本だけ傾けたり、背を低くしたりできます。

Drawの時間と、描画命令の回数を分ける

ドローコール(Draw Call) は、GPUへ描画を指示する命令です。条件が揃う描画をまとめれば、命令を扱う負担を減らせます。このように仕事をまとめることを バッチング と呼びます。

ただし、柱が32本なら32回、ISMなら必ず1回、とは決まりません。形の中で使うマテリアル、影などを描く別の処理、LOD(細かさの違うモデル)の選択によって分かれます。もとのActor配置でも、エンジンが自動で描画をまとめている場合があります。

確認したいこと見るもの
描画を準備するCPU側の時間stat unit のDraw(ms)
描画命令の数の変化stat scenerendering のMesh draw callsなど
ゲーム全体が軽くなったかFrameと、Game・Draw・GPUの時間

Drawは回数ではなく時間 です。大きければ描画準備を調べるきっかけになりますが、それだけで原因をドローコールに絞れません。statコマンドの記事と合わせて、同じ場面の変更前後を見ます。

ISMにしても、画面に映る柱の面やピクセルが自動で減るわけではありません。その一方で、多数のActor・Componentを個別に管理する負荷は減らせます。描画命令の数だけで、効果のすべてを判断しないようにしましょう。

参考:Instanced Static Mesh ComponentMerging ActorsFoliage ModeAdd Instance

実践:配置済みの小物をまとめて比べる

最初はBlueprintで大量生成せず、同じ場所にある小物をISMへ置き換える 方法で確かめます。配置を保てるので、「位置が変わったから軽くなった」と混同しにくくなります。

比較用のレベルを二つ用意する

歩けるThird Personテンプレートのレベルを、練習用に保存して使います。

  1. Content Browserの「Settings → Show Engine Content」をオンにします。
  2. 「Engine → BasicShapes」のSphereを選んで Ctrl + C。自分のContentに作った練習用フォルダで Ctrl + V を押し、SM_InstanceProbe と名付けます。
  3. コピーを開き、「Nanite Settings → Enable Nanite Support」をオフにします。変更した場合は「Apply Changes」を押して保存します。
  4. 球を床の上へ一個配置し、Alt を押しながらドラッグして複製します。数個をまとめて選択して複製すると、32個程度まで増やしやすくなります。
  5. 見通しのよい場所で、球が重なりすぎないよう数列に並べます。まずは全体を見渡せる小さな範囲で十分です。

これを L_Instances_A として保存し、「File → Save Current Level As」で L_Instances_B も作ります。Aは比較の出発点、Bは変換する側です。数を増やす場合も、二つに分ける前に揃えておきます。

BだけをBatchでまとめる

Bを開き、球のActorだけを選択します。床、Player Start、ライトなどは含めません。

  1. 上部メニューの「Actor → Merge Actors → Merge Actor Settings」を開きます。
  2. 方法を Batch にします。同じメッシュをインスタンスへまとめる方法です。
  3. 「Select the type of Instanced Component」で Instanced Static Mesh Component を選びます。
  4. 「Instance Replacement Threshold」を 2 にします。同じメッシュが何個以上あれば変換するか、という条件です。
  5. 「Replace Source Actors」をオンにして「Merge Actors」を実行します。B内の元の球を、生成されたActorへ置き換えます。
同じ球を選び、Merge ActorsのBatchでISMへまとめる

生成されたActorを選び、DetailsでISMコンポーネントとインスタンス数を確認します。球が32個なら32個分の配置が残り、見た目の位置も同じであることを確かめてから保存します。変換対象の設定によっては、コンポーネントが複数に分かれる場合もあります。

元の球と変換後の球が両方残っていると、二重に描く比較になります。Bで元のActorが置き換わったかをOutlinerでも確認してください。やり直すときはAからBを作り直せます。

同じ視点で計測する

AとBをそれぞれStandaloneで起動し、同じ場所・向きから見ます。Player Start、画質、解像度、FPS上限は共通にし、読み込み直後を避けて値を控えます。

起動したゲームのコンソールで stat unitstat scenerendering を入力すると、時間と描画命令数を表示できます。表示の開き方は、先ほどのstatコマンドの記事で確認できます。

AとBの同じ球の配置を、同じカメラから比較する
記録するものA:個別ActorB:ISM
見える球の数と配置変更前を確認同じか確認
Frame / Game / Draw / GPUそれぞれmsを記録同じ条件で記録
Mesh draw calls表示された数を記録変化を見る

32個程度では、時間の差が小さくても不思議ではありません。仕組みを確認できたら、128個、256個と増やした比較を試せます。何ミリ秒下がるかは、使うモデルと実行環境次第 です。

  • 描画命令が減ってFrameも短くなったら、今の場面では有効な変更です。
  • 命令が減ってもFrameが変わらなければ、GPUの別の仕事やFPS上限なども見ます。
  • 命令自体があまり変わらなければ、元からの自動インスタンシングや、対象以外の描画を調べます。

差が不明瞭なら、一度Aへ戻って同じ傾向が出るか確かめます。小さな値の上下だけで結論を急がず、実際に遊ぶ場面でも確認しましょう。

Sponsored

ISM・HISM・Foliageを使い分ける

同じ形を並べる方法は、ISMだけではありません。まず「どう配置するか」「どれくらい動くか」で候補を選びます。

ISMは基本の配置、HISMは動かない群れ、Static Mesh Foliageはブラシで配置する
方法考え方試したい場面
ISM一つのコンポーネントに複数の配置を持つまず試す基本。配置を動かす場合やNaniteとの併用
HISM配置を空間的なグループの階層にまとめる数千規模で、ほぼ動かない草木や岩
Static Mesh Foliageブラシで塗り、内部でインスタンス化する地形へ自然物を手早く配置したい

HISM の階層は、広い範囲を小さなグループに分けて「どの一帯が見えるか」を絞るためのものです。動かない大量の配置では役立ちますが、配置を頻繁に変えると階層の更新も負担になります。

現行のISMも、インスタンスごとのLODとカリングに対応しています。「ISMは遠い物も全部描く」「大量なら無条件でHISM」と覚える必要はありません。まずISMを試し、HISMが合いそうな場面で置き換えて比べます。

Foliageには Actor Foliage もあります。こちらはActorを配置する種類で、Static Mesh Foliageと同じ描画のまとめ方を期待するものではありません。ランドスケープの記事から使う場合も、どちらを置いているか確認します。

Blueprintで柱を一本、八本と増やす

手作業の配置をまとめる方法が分かったら、次はBlueprintから増やしてみます。道沿いの柱や、部屋の大きさに合わせて並べる小物に応用できます。

まず一本だけ出す

Actorを親に BP_InstanceRow を作ります。「Components → Add」からInstanced Static Meshを追加し、名前を Posts にします。DefaultSceneRootは残し、Postsの位置・回転は0、スケールは各軸1にします。

Postsの「Static Mesh」にはEngineのBasicShapesにある Cube を指定します。練習用にコピーする場合は、最初のSphereと同じ手順です。「Mobility」は動かせる設定の Movable、今回は描画だけを見るため「Collision Presets」は当たり判定を使わない NoCollision にします。「Instances」へ手動で要素は追加せず、空のままにします。

BP_InstanceRowのPostsにCubeを指定し、配置は実�行時に追加する

Event GraphでPostsをドラッグしてGetを置き、そこから Add Instance を作ります。このノードは、指定したISMコンポーネントへ一個分の配置を追加します。

  1. Event BeginPlayの実行出力を、Add Instanceの実行入力へつなぎます。
  2. Postsの出力を、Add Instanceの Target へつなぎます。
  3. Make Transform を置き、Locationを (0, 0, 50)、Rotationを (0, 0, 0)、Scaleを (0.5, 0.5, 1) にします。
  4. Make TransformのReturn Valueを、Add Instanceの Instance Transform へつなぎます。
  5. Add Instanceの World Spaceはオフ にします。
BeginPlayからAdd Instanceを実行し、PostsとMake Transformの値を渡す

Make Transformは値を組み立てるノードなので、白い実行線はつなぎません。Targetは「どのISMへ追加するか」、Instance Transformは「どこへ、どの向き・大きさで置くか」です。

World Spaceがオフのとき、座標の基準は Postsの位置と向き です。BP_InstanceRowをレベルの別の場所へ動かせば、柱も一緒に移ります。ワールド全体の原点から指定したいときにオンを使います。

Compileして保存し、BP_InstanceRowをレベルへ一個配置します。Actorの回転は0、スケールは各軸1のまま、原点を床の高さに合わせてPlayしてください。標準Cubeは一辺100cmなので、このScaleでは幅50cm・高さ100cmの柱になります。中心をZ=50へ上げることで、底が床に合います。

一本出れば成功です。出ないときは、PostsのStatic Mesh、実行線、Scaleが0になっていないか、Actorをレベルへ配置したかを確認します。

同じ接続を、八回繰り返す

今のAdd InstanceとMake Transformを使い、次のように変えます。

  1. BeginPlayとAdd Instanceの間に For Loop を入れます。First Indexは 0、Last Indexは 7 です。
  2. For Loopの Loop Body をAdd Instanceの実行入力へつなぎます。Completedは未接続で構いません。
BeginPlayからFor Loopを実行し、Add Instanceを八回呼ぶ

この段階では同じ場所へ八本が重なります。次に、繰り返すたびに位置が変わるようにします。下図のFor LoopとMake Transformは、今つないだものと同じノードです。新しく二組作る必要はありません。

  1. Indexから整数の Multiply(×) を作り、もう一方へ 200 を入れます。
  2. Make Vector を置き、Xへ乗算の結果、Yへ0、Zへ50を入れます。整数から小数への変換が必要なら自動変換を使います。
  3. Make VectorのReturn Valueを、既存Make TransformのLocationへつなぎます。他の値はそのままです。
同じFor LoopのIndexを200倍し、Make VectorからMake TransformのLocationへ渡す

図の「i → f」は、整数を小数として扱えるようにする自動変換を表しています。

Indexは0、1、2…7と変わるため、Xは0、200、400…1400になります。0から7までは 八回 です。200cm、つまり2m間隔の柱が一本の列になります。

一本の柱から、2m間隔の八本の列へ増やす

もう一度Playし、柱が八本並べば成功です。Last Indexを3へ変えると四本、間隔を300へ変えると3m間隔になります。同じ形を使い、配置情報だけで景色を変えられることが分かります。

この処理はBeginPlayで一度だけ動きます。Tickへつなぐと毎フレーム追加され続けるため、そのまま移さないでください。何度も並べ直す機能にするときは、先にClear Instancesで以前の配置を消すなど、作り直し方も決めます。

Sponsored

番号を使って変更・削除する

Add InstanceのReturn Valueは、追加した配置の インデックス です。Postsの中の何番を操作するか、という番号で、Actorへの参照とは違います。

ノード役割
Add Instance配置を追加し、その番号を返す
Update Instance Transform指定番号の位置・回転・スケールを変える
Remove Instance指定番号の配置を削除し、成功したか返す
Clear Instancesそのコンポーネントの配置をすべて消す

たとえば一本だけ柱を動かすなら、追加時の番号をUpdate Instance Transformへ渡します。座標空間を追加時と揃え、一回の変更を表示へ反映したい場合は Mark Render State Dirty をオンにします。

インデックスは、変わらないIDではない

削除や作り直しが入ると、同じ番号が別の配置を指すことがあります。後ろが順に詰まる方式も、末尾の配置が空いた番号へ移る方式もあるため、「削除した後ろだけ、番号を一つ減らせばよい」と決めつけないでください。

途中を削除すると番号と物の対応が変わるため、番号を固定IDとして扱わない

今回のように作って並べるだけなら、番号を長期間保存する必要はありません。伐採した木や採取済みの岩を記録したくなったら、木や岩ごとに付ける変わらないIDと、ISM内の番号を分けて管理します。まずは一個の変更・削除を試し、その後で削除後の対応表も更新する設計へ進めます。

「消す代わりに地下へ移動する」だけでは、配置データや当たり判定が残る場合があります。表示を隠すことと、使わなくなった配置を取り除くことは別です。

当たり判定は持てるが、独立したActorではない

ISMにもコリジョンを設定でき、個々の柱にぶつかれます。先ほどNoCollisionにしたのは、配置を確かめやすくするためです。

ただし、柱ごとに独立したEvent GraphやHP変数ができるわけではありません。材質やコリジョンの設定も基本的にコンポーネントで共有します。一本ずつ壊す、燃やす、会話するといった反応が必要なら、管理側がどの配置への操作かを識別する仕組みを考えます。

初心者のうちは、個別の振る舞いが多い物をActorで作り、繰り返す背景からISMを試すと進めやすくなります。「ISMでは絶対に反応を作れない」という制限ではなく、どこで振る舞いを持たせるかの違いです。

距離カリングとNaniteの関係

距離で消すことは、まとめて描くこととは別

ISMへ置き換えただけで、好きな距離から小物が消えるわけではありません。距離カリング は「ここから先は描かない」という別の調整です。

先ほどCubeをコピーしていなければ、ここで練習用のコピーを作ります。そのNaniteをオフにしてPostsへ割り当て、Detailsで次の値を設定してPlayします。カメラを柱の列から離してみましょう。

設定練習用の値意味
Instance Start Cull Distance1000フェード用の値が変わり始める距離、10m
Instance End Cull Distance1500描画から除外する距離、15m

Endを超える側の柱が消え、近づくと戻るかを確かめます。急に出入りするなら、実際のゲームではもっと遠くまで残す必要があります。前後の性能を比べるときは、まず両方の距離を0に戻し、距離で消す効果を混ぜないようにします。

不透明な柱は距離で非表示になり、Startの値だけでは半透明にならない

Startを入れるだけで、普通の不透明マテリアルが薄くなるわけではありません。 滑らかに消すには、PerInstanceFadeAmountというフェード用の値をマテリアルで読み、切り抜きなどへ反映する作りが必要です。今回の練習はEndによる非表示を確かめれば十分です。

消えない場合はNaniteがオフか、Endが0のままでないか、カメラが十分離れたかを確認します。LOD・カリングの記事も合わせて、見た目と負荷の両方を調整します。

NaniteとISMは併用できる

Nanite は、細かなモデルを必要な範囲・細かさで描く仕組みです。ISMでNaniteメッシュを使うこともできます。

ISMは繰り返す配置をまとめ、Naniteは形の細かさと可視性を扱う

Nanite側で描画が効率化されていても、個別のActor・Componentを減らす効果まで同じとは限りません。「NaniteだからISMは不要」と決めず、FrameやGameの時間、管理する配置の数も見ます。

Naniteを使う場合はISMを基本に考えます。ただし、先ほどの従来メッシュ向け距離カリングやフェードを、そのまま適用できるとは限りません。使用する版と配置方法の対応範囲は、Naniteの記事で確認してください。

おまけ:先に知っておくと良いこと

種類や設定が違えば、分けてまとめる

柱と岩など、異なる形は別のISMコンポーネントへ分けます。同じ形でも、共有できないマテリアルや設定があればまとまり方が変わります。個体ごとに色を変えたい場合は、Per Instance Custom Dataという個々の配置用の数値をマテリアルへ渡す方法があります。

PCGやFoliageでは、すでにインスタンス化されていることもある

PCGのStatic Mesh SpawnerやStatic Mesh Foliageは、こうした配置を作る入り口です。大量に見える物が、最初から一個ずつのActorとは限りません。今どんな形で配置されているかを確かめてから変換します。

変更が多いなら、その更新時間も測る

何百個ものTransformを毎フレーム変えたり、頻繁に生成・削除したりする場合は、その更新も仕事になります。静止時だけ軽くても、操作中に引っかかるならUnreal Insightsで重い区間を見ます。

まずは、ゲーム内で何度も使っている小物を一種類選んでみてください。同じ景色を保ったまま、配置の持ち方を変えて比べる。その小さな実験から、どこをISMへ任せるとよいかが見えてきます。

まとめ

  • 描画命令の回数が減ると、stat unit のDrawの時間が下がる
  • ISMは「同じメッシュ・同じマテリアル」を1回でまとめて描く
  • 位置や大きさは配置ごとに変えられるが、材質は共有される
  • 削除は番号がずれるので、扱い方を決めてから使う

使う前の問いかけは、「これは同じ物が何十個も並ぶか」 です。並ぶならISM、1つずつ違うなら普通のActorのままで構いません。

自動で並べるなら PCG入門、描画を減らす他の手は LODとカリング にあります。

Unreal Engine このセクションのノート98