Unity Term Book
グラフィックスとエフェクト

Material & Shader

Shader はピクセル描画を決める GPU プログラム、Material はその具体値(色・テクスチャ・Smoothness)を持つインスタンスです。PBR、sharedMaterial、MaterialPropertyBlock でバッチを守る書き方を学べます。図解とシミュレーターで PBR 表面を調整できます。

想像してみてください...

Shader は塗料のレシピ(木、金属、ガラス…)。Material はそのレシピの特定の缶—— 同じ金属レシピでも、金、銀、より光沢がある缶ができます。一つの Shader から 何千もの Material を作り、見た目を変えられます。GameObject は Mesh Renderer で 割り当てた Material をメッシュに「塗ります」。

概念の詳細

Shader は GPU 上で動く HLSL(High Level Shading Language) プログラムです。少なくとも二つのステージがあります:Vertex Shader(3D 頂点を 2D 画面へ)と Fragment/Pixel Shader(各ピクセルの最終色)。Unity はこれを ShaderLab、 Surface Shaders、または URP の Lit/Unlit Shader Graph で包みます。

Material は Shader を参照し、properties の値を持つアセットです: メイン色(_BaseColor)、テクスチャ( _BaseMap)、metallic(_Metallic)、roughness( _Smoothness)… 各 Renderer はサブメッシュに対応する一つ以上の Material スロットを持てます。

性能では Material instancing が重要:同じ Material アセットを共有する 多くの物体は一つのドローコールにまとめられます(GPU instancing または static batching)。 renderer.sharedMaterial ではなく renderer.material(私有コピー)を使うと、 物体ごとにドローコールと追加メモリが増えます。

Unity 標準シェーダー:URP/Lit(フル PBR)、URP/Unlit(ライティングなし)、 Sprites/Default(2D)、Particles/Standard Unlit (パーティクル)。Shader Graph と HLSL で完全カスタム効果も作れます。

Shader → Material → Renderer

📄 Shader (HLSL program)

URP/Lit — properties と描画ロジックを定義

_BaseColor_Metallic_BaseMap
▼ instantiate

Material A

_BaseColor = Red
_Metallic = 0.9

Material B

_BaseColor = Blue
_Metallic = 0.0

Material C

_BaseColor = Gold
_Metallic = 1.0

▼ assign to

🏠 House
Mat A

🚗 Car
Mat B

🏆 Trophy
Mat C

🔑 Key
Mat C

Trophy + Key が Mat C を共有 → 1 draw call(batching)

ハンズオン手順

1

新しい Material を作成

Project → 右クリック → Create → Material。分かりやすい名前(Metal_Gold、Ground_Grass…)。

2

適切な Shader を選ぶ

Inspector → Shader ドロップダウン:PBR は URP/Lit、自己発光面は URP/Unlit、2D は Sprites/Default。

3

テクスチャを割り当てプロパティを調整

Base Map にテクスチャをドロップ。Metallic(0=プラスチック、1=金属)、Smoothness(0=マット、1=鏡)。

4

MeshRenderer に Material を割り当て

MeshRenderer Materials[0] にドロップするか、Scene ビューの GameObject にドラッグ。

5

スクリプトからプロパティを変更

renderer.sharedMaterial.SetColor("_BaseColor", color) — または Material をクローンしない MaterialPropertyBlock。

インタラクティブシミュレーター

PBR パラメータを調整して球の表面変化を観察——Unity の Material Inspector の代替。

// Material Properties

_BaseColor = "#4488ff"

_Metallic = 0.50

_Smoothness = 0.70

_Emission = 0.00

Shader: URP/Lit

青い光沢プラスチック

コード例

基本

実行時に Material の色と metallic を変更する。

using UnityEngine;

public class MaterialController : MonoBehaviour
{
  Renderer rend;

  void Start()
  {
      rend = GetComponent<Renderer>();

      // sharedMaterial: shared with every object → no extra copy
      rend.sharedMaterial.SetColor("_BaseColor", Color.red);

      // material (not shared): a private copy for this object
      rend.material.SetFloat("_Metallic", 0.9f);
      rend.material.SetFloat("_Smoothness", 0.8f);
  }

  public void Flash(Color color)
  {
      // Flash trick: set emission color
      rend.material.SetColor("_EmissionColor", color * 2f);
      DynamicGI.SetEmissive(rend, color * 2f);
  }
}

コード例

上級

MaterialPropertyBlock — Material をクローンせず、バッチを崩さずにオブジェクトごとのプロパティ。

using UnityEngine;

// Color each instance differently WITHOUT breaking GPU Instancing/Batching
public class InstanceColorizer : MonoBehaviour
{
  static readonly int ColorID  = Shader.PropertyToID("_BaseColor");
  static readonly int EmitID   = Shader.PropertyToID("_EmissionColor");

  MaterialPropertyBlock mpb;
  Renderer rend;

  void Awake()
  {
      rend = GetComponent<Renderer>();
      mpb = new MaterialPropertyBlock();
  }

  public void SetColor(Color color)
  {
      rend.GetPropertyBlock(mpb);          // Read current state
      mpb.SetColor(ColorID, color);       // Change color
      rend.SetPropertyBlock(mpb);          // Apply — no new Material
  }

  public void SetEmission(Color emitColor)
  {
      rend.GetPropertyBlock(mpb);
      mpb.SetColor(EmitID, emitColor);
      rend.SetPropertyBlock(mpb);
  }
}

📌 要点

  • Shader = レシピ、Material = 具体値のインスタンス
  • sharedMaterial: 共有、追加 RAM なし
  • MaterialPropertyBlock: インスタンスごと、バッチ維持
  • Metallic=1 + Smoothness=1 = 完璧な鏡
  • 毎フレーム文字列より Shader.PropertyToID() が速い

⚠️ よくあるミス

  • ❌ スポーンループ内で renderer.material を使う

    毎回 Material クローン → メモリリーク

    ✅ MaterialPropertyBlock か sharedMaterial を使う

  • ❌ Material で Emission を有効にし忘れる

    SetColor("_EmissionColor",...) は Emission オンまで無効

    ✅ 先に Material Inspector で "Emission" にチェック