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 と描画ロジックを定義
Material A
_BaseColor = Red
_Metallic = 0.9
Material B
_BaseColor = Blue
_Metallic = 0.0
Material C
_BaseColor = Gold
_Metallic = 1.0
🏠 House
Mat A
🚗 Car
Mat B
🏆 Trophy
Mat C
🔑 Key
Mat C
Trophy + Key が Mat C を共有 → 1 draw call(batching)
ハンズオン手順
新しい Material を作成
Project → 右クリック → Create → Material。分かりやすい名前(Metal_Gold、Ground_Grass…)。
適切な Shader を選ぶ
Inspector → Shader ドロップダウン:PBR は URP/Lit、自己発光面は URP/Unlit、2D は Sprites/Default。
テクスチャを割り当てプロパティを調整
Base Map にテクスチャをドロップ。Metallic(0=プラスチック、1=金属)、Smoothness(0=マット、1=鏡)。
MeshRenderer に Material を割り当て
MeshRenderer Materials[0] にドロップするか、Scene ビューの GameObject にドラッグ。
スクリプトからプロパティを変更
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" にチェック