LoginSignup
6
3

More than 3 years have passed since last update.

[MaterialPropertyDrawer] [Unity] ShaderPropertyAttributeを自作した

Last updated at Posted at 2019-11-13

CustomMaterialEditorを各シェーダーごとに作成するのは大変なので
簡単なデザインをできるようにいろいろと作ってみました。

ShaderPropertyAttributeとは

シェーダーのプロパティに属性を付与できる機能のことです
マテリアルのインスペクタでの表示を変えることができます。
例:[Header(Hoge)], [NoScaleOffset]など

以下の記事で公式で用意されているものが紹介されています。
【Unity】シェーダプロパティアトリビュートまとめ
【Unity】ShaderLabのプロパティ属性まとめ

ShaderPropertyAttributeを自作する

この属性ですが, MaterialPropertyDrawerを継承することで自作できます。
公式リファレンスに実装例が載っています

また、私が作成したプログラムもgistで公開しているので参考にどうぞ
https://gist.github.com/gatosyocora/9f506612a27a02e28e0be60d09535580

コード例です。

SampleAttribute1.cs
internal class SingleLineTexDrawer : MaterialPropertyDrawer
{
    public SingleLineTexDrawer() { }

    public override void OnGUI(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor)
    {
        editor.TexturePropertySingleLine(label, prop);
    }
}

これはTexture2Dを1行で表示するようにするAttributeです。
こんな感じになります
image.png

このAttributeでは単にTexture2Dのプロパティの表示を
MaterialEditor.TexturePropertySingleLine()で変えているだけです。

ここで注意する点は

  • MaterialPropertyDrawerを継承する
  • OnGUIをOverrideする
  • クラス名を○○Drawerにする
  • ファイル名とクラス名は一致していなくても良い
  • Editorフォルダ以下に入れる

このattributeはシェーダーコードではこのように書きます
作成したクラスのクラス名からDrawerを除外した部分を記入することになります。

sample1.shaderの一部
Properties
{
    [SingleLineTex]
    _TestTex ("TestTex", 2D) = "while" {}
}

もう一例をあげます

SampleAttribute2.cs
internal class LineDecorator : MaterialPropertyDrawer
{
    private float spaceSize;

    public LineDecorator()
    {
        spaceSize = 0;
    }

    public LineDecorator(float spaceSize)
    {
        this.spaceSize = spaceSize;
    }

    public override void OnGUI(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor)
    {
        GUILayout.Space(spaceSize);
        GUILayout.Box(string.Empty, GUILayout.ExpandWidth(true), GUILayout.Height(1));
        GUILayout.Space(spaceSize);
    }
}

これは区切り線を入れるAttributeでこんな感じの表示になります
image.png

区切り線の上下に空白を入れるようにしており、その高さを自分で設定できるようにしています。
シェーダーコードにはこのように書きます

sample2.shaderの一部
Properties
{
    [Line(10)]
    _Color ("Color", Color) = (1, 1, 1, 1)
}

ここで指定した10がLineDecorator(float spaceSize)の引数として入力されます。

ShaderPropertyAttributeの種類

ShaderPropertyAttributeですが、実は2種類あります。

Drawer

プロパティの表示自体に影響を与えるもの
プロパティにつき1つしかつけることができない
例: [HideInInspector] [Toggle] [Enum] [NoScaleOffset]
上記の例だとSingleLineTexDrawer

Decorator

マテリアルのインスペクターに影響を与えるもの
プロパティにつきいくつでも設定できる
例: [Space] [Header]
上記の例だとLineDecorator

Drawerはプロパティの表示自体を変えるが、
Decoratorは余白やタイトルなどの装飾をつけるときに使います。

これらはクラス名でどちらの種類かが区別されているようです。
Attributeによって適切なほうを使うのが良いです。
また、内部処理的に各プロパティごとに
すべてのDecoratorのOnGUIの実行後にDrawerのOnGUIを実行しているようです。

6
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
3