1.

UE5 のマテリアルとマテリアルインスタンス|違いと使い分け

編集

この記事の要点

  • マテリアルは「シェーダの設計図」、マテリアルインスタンスは「親を参照し、値の上書きだけを持つ子アセット」(複製ではなく、コンパイル済みシェーダは親と共有)。ノード構造を持てるのは親のマテリアルだけ。
  • 親を編集するとシェーダの再コンパイルが走るが、インスタンスの数値パラメータを変えるだけなら再コンパイルは発生しない。
  • 例外はスタティックスイッチなどの「静的パラメータ」と、ブレンドモードなどのプロパティ上書き。これらは新しいシェーダ順列を生むので数を絞る。
  • 実行時に色や値を動かしたいときだけマテリアルインスタンスダイナミック(MID)を使う。静的な見た目違いはアセットのインスタンスで足りる。
  • 実務の基本形は「マスターマテリアルを少数だけ作り、実際にメッシュへ割り当てるのは全部インスタンス」。

Unreal Engine 5 (UE5)マテリアル を作り始めると、必ず「マテリアル」と「マテリアルインスタンス」という2種類のアセットに出くわします。パラメータをいじりたいだけなのに毎回コンパイル待ちが入る、色違いを作るたびにマテリアルが増える——こうした詰まりの多くは、この2つの役割を分けて考えていないことが原因です。この記事では両者の構造上の違い、パラメータ化の手順、パフォーマンスに実際に効くポイントを整理します。

12つのアセットの役割の違い

マテリアル(Material)は、ノードグラフを持つ本体です。ベースカラーやラフネス、法線といった出力ピンにノードをつないで、そのサーフェスがどう計算されるかを定義します。この「計算の手順」は描画時にシェーダコードへ変換され、プラットフォームごとにコンパイルされます。つまりマテリアルの編集は、シェーダのソースコードを書き換えることと同じ意味を持ちます。

一方のマテリアルインスタンス(Material Instance)は、ノードグラフを一切持ちません。持っているのは「どのマテリアルを親にするか」という参照と、「親が公開しているパラメータにどんな値を入れるか」という値のリストだけです。だから編集画面にはノードグラフがなく、チェックボックスとスライダーが並んでいます。値を差し替えているだけなので、計算手順そのものは親と完全に同一です。

マスターマテリアル ノードグラフを持つ BaseColor パラメータ Roughness パラメータ Texture パラメータ 編集=シェーダ再コンパイル インスタンス:木材(茶・粗い) 値だけ差し替え/再コンパイル不要 インスタンス:金属(灰・つるつる) 値だけ差し替え/再コンパイル不要 インスタンス:塗装(赤・つや) 値だけ差し替え/再コンパイル不要
1つのマスターマテリアルから、値の違うインスタンスを量産する。これが UE5 のマテリアル運用の基本形。
項目マテリアルマテリアルインスタンス
ノードグラフ持つ(編集できる)持たない
編集画面ノードエディタパラメータ一覧
値の編集ノードを差し替えるチェックを入れて値を上書き
シェーダ再コンパイル編集のたびに発生する数値・色・テクスチャの変更では発生しない
親子関係ルートになるマテリアルにも別のインスタンスにも親を取れる
実行時の値変更できないMID を作れば可能

2なぜインスタンスを使うと速いのか

「インスタンスにすると軽くなる」とよく言われますが、描画そのものが劇的に軽くなるわけではありません。効いているのは主に次の3点です。

1つ目はシェーダの数が減ることです。マテリアルを10個作れば、それぞれ別のシェーダとしてコンパイルされ、パッケージにも10個分のバイナリが載ります。一方、1つのマスターから10個のインスタンスを作れば、コンパイルされるシェーダは基本的に1種類だけで、各インスタンスは違うパラメータ値を渡すだけです。ビルド時間とパッケージサイズ、そしてメモリに直接効きます。シェーダコンパイルに長時間待たされる問題とその解決策 の通り、シェーダ順列の総数はプロジェクト後半ほど効いてきます。

2つ目はイテレーション速度です。親マテリアルを編集すると、そのマテリアルとすべての子インスタンスのシェーダが作り直されます。インスタンス側でパラメータを動かせば、その待ち時間がゼロになります。

3つ目はドローコールのマージ余地です。同じシェーダを使うオブジェクト同士は、レンダラ側でまとめて処理しやすくなります。特にメッシュを大量配置する場面では、マテリアルがバラバラだと本来まとめられた描画が分割されます。

○ 使うべき場面
色・粗さ・テクスチャだけが違うバリエーションを作るとき。木材、金属、塗装、布——量産アセットの大半はこのパターンに収まる。
△ 注意
インスタンスにしても「命令数(Instruction Count)」は親と同じ。重いノードグラフを組んだ親から作ったインスタンスは、当然重いまま。軽量化は親側で行う。

3パラメータ化の手順

インスタンスから値を触れるようにするには、親側でノードを「パラメータ」に変換しておく必要があります。パラメータでない定数はインスタンスの一覧に出てきません。「インスタンスを作ったのに何も出てこない」という詰まりは、ほぼこれが原因です。

  1. 親マテリアルを開き、パラメータにしたい定数ノード(Constant、Constant3Vector、Texture Sample など)を選ぶ。
  2. 右クリックしてパラメータへの変換を選ぶ。Constant はスカラー、Constant3Vector はベクター、Texture Sample はテクスチャパラメータになる。
  3. 詳細パネルで Parameter Name を分かりやすい名前に変える。この名前はインスタンス側の表示名になり、Blueprint からの指定にも使われる。後から変えると既存インスタンスの上書き値との紐付けが切れて既定値に戻るので、命名は最初に決めておく。
  4. 同じパネルで Group を設定する。「Base Color」「Normal」「Tiling」のように切っておくと、インスタンスのパラメータ一覧が折りたたみ見出しで整理され、数が増えても迷わない。
  5. 並び順を制御したい場合は Sort Priority を設定する。未設定だと名前順に並ぶため、重要なパラメータが下に埋もれやすい。
  6. 親を保存し、コンテンツブラウザで親マテリアルを右クリックしてマテリアルインスタンスを作成する。
  7. インスタンスを開き、使いたいパラメータの左にあるチェックボックスをオンにしてから値を編集する。チェックを入れないと上書きされず、親の既定値が使われ続ける点に注意。

チェックボックスの意味は「このインスタンスがこの値を自分で持つかどうか」です。外しておけば親の値に自動で追従します。全部にチェックを入れると親の調整が子に伝播しなくなるので、本当に変えたいものだけをオンにするのがコツです。

4静的パラメータだけは扱いが違う

ここが一番の落とし穴です。パラメータの中には、値を変えるとシェーダの構造そのものが変わる種類があります。代表がスタティックスイッチパラメータ(Static Switch Parameter)で、「この機能を使うか使わないか」をブール値で切り替えるノードです。

スタティックスイッチは実行時の分岐ではありません。コンパイル時に、使わない側の枝ごとシェーダから削除されます。だからこそ「ディテールノーマルを使う/使わない」といった機能のオンオフに向いており、オフにした分だけ本当に軽くなります。その代わり、インスタンス側でこの値を切り替えると新しいシェーダ順列が生まれ、再コンパイルが発生します

同じことが「マテリアルプロパティの上書き(Material Property Overrides)」にも当てはまります。インスタンスの詳細パネルからブレンドモードやシェーディングモデル、両面表示などを上書きできますが、これらもシェーダの構造を変えるためコンパイルが走ります。

○ 使うべき場面
スタティックスイッチは「機能のオンオフ」に。オフにしたインスタンスでは、その機能に使われていたテクスチャサンプリングや計算がまるごと消えるので、モバイルや大量配置で効く。
△ 注意
スイッチを N 個入れると、組み合わせは最大 2 の N 乗まで増える。10個入れれば理論上1024通り。増やしすぎるとビルドが終わらなくなるので、スイッチは本当に必要なものだけに絞る。

5実行時に値を変える:MID

ダメージを受けたら赤く光る、といったゲーム中の変化にはマテリアルインスタンスダイナミック(MID)を使います。MID はアセットではなく、実行時にメモリ上へ作られるインスタンスです。ブループリント (Blueprint) から次の流れで扱います。

BeginPlay
  └ Create Dynamic Material Instance
       Source Material : 親マテリアル or マテリアルインスタンス
       Target          : 対象の Mesh Component
       戻り値 → 変数 MyMID に保存

任意のイベント(被弾など)
  └ Set Scalar Parameter Value (Target = MyMID, ParameterName = "DamageAmount", Value = 0.8)
  └ Set Vector Parameter Value (Target = MyMID, ParameterName = "TintColor",   Value = 赤)

実装上のポイントは3つです。第一に、MID は毎フレーム作らないこと。生成にはコストがあるので、BeginPlay や Construction Script で1回だけ作って変数に保持し、以降はその変数に Set します。毎ティック作り直す実装は典型的なパフォーマンス事故です。

第二に、パラメータ名は文字列で指定するため、親側でリネームすると静かに効かなくなります。エラーも出ないので原因究明に時間を取られがちです。名前を変えたら Blueprint 側も必ず追従させてください。

第三に、MID はコンポーネント単位で作られるため、同じアクターを大量に並べて全部に MID を作ると、その分だけメモリと更新コストが乗ります。全体で一斉に同じ値を変えたいだけなら、マテリアルパラメータコレクション(Material Parameter Collection)で1箇所の変更を全マテリアルへ届けるほうが軽く済みます。天候や時間帯のようなグローバルな値はこちらが適任です。

6実務での使い分け早見表

やりたいこと使うもの理由
新しい質感ロジックを作るマテリアル(親)ノードグラフを持てるのは親だけ
色・粗さ・テクスチャ違いを量産するマテリアルインスタンス再コンパイル不要、シェーダは1種類で済む
機能のオン/オフを切り替えるスタティックスイッチ+インスタンス不要な計算がコンパイル時に削除される
ゲーム中に色や値を動かすMID実行時に Set できる唯一の手段

7よくある失敗と回避策

マスターマテリアルを作りすぎる。 「壁用」「床用」「小物用」と分けたくなりますが、パラメータで吸収できる違いなら1つにまとめたほうが管理も描画も有利です。逆に、スイッチを何十個も抱えた巨大マスターも失敗です。プロジェクト全体で用途別に数個〜十数個に収まるのが健全な形です。

インスタンスの親をあとから差し替える。 親を変更すると、パラメータ名が一致しないものは上書き値が失われます。移行前にパラメータ名を揃えておくと被害を減らせます。

インスタンスの階層を深くしすぎる。 インスタンスは別のインスタンスを親に取れるので、「木材マスター → オーク → 濡れたオーク」のような階層が作れます。共通調整を上流でまとめられる反面、深いと「この値はどこで上書きされたのか」が追えなくなります。2〜3段までが実用的です。

親の既定値を放置する。 既定値は「チェックを入れていないインスタンス全部」に効きます。暫定値のままだと、親をいじった瞬間に多数のアセットの見た目が変わります。

マテリアルの構造が固まると、ライティング の調整と質感の調整を行き来する場面が増えます。そのときインスタンス側だけで完結できていれば、コンパイル待ちなしでリアルタイムに見比べられます。これが「マスター+インスタンス」を徹底する最大の実利です。

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. マテリアルとマテリアルインスタンスの違いと使い分け
  2. よく使うマテリアルノード(Lerp / Fresnel / Panner / Texture Sample)
  3. マテリアルのブレンドモードと Two Sided の設定