【Unity】ShaderGraphで作成したシェーダーのInspectorを拡張する

はじめに

今回はShaderGraphで作成したシェーダーのInspectorを拡張する方法を紹介します

環境は Unity 2021.3.25f1です

Universal Render Pipeline を使用しています。

拡張方法

ShaderGraphで作成したシェーダーのInspectorを拡張する

ShaderGraphで作成したシェーダーのInspectorを拡張するにはShaderGUIを継承したクラス名をCustomEditorGUIに設定することでマテリアルに表示状態を変更できます。

試しに何も表示しないShaderGUIを継承したクラスを作成してCustomEditorGUIに設定してみましょう

#if UNITY_EDITOR
using UnityEngine;
using UnityEditor;//ShaderGUIで使用

public class TestShaderGUI : ShaderGUI
{
    public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties)
    {
       // base.OnGUI(materialEditor, properties);
    }
}
#endif

マテリアルになにも表示されなくなりました

ShaderGraphで作成したシェーダーに元々表示されていたパラメータを表示する

継承クラスをBaseShaderGUIに変更します。これはShaderGraphUnlitGUIクラスで使用されているものでShaderGraphで作成したシェーダーのInspector表示処理が一部実装されています

#if UNITY_EDITOR
using UnityEngine;
using UnityEditor;//ShaderGUIで使用
using System.Collections.Generic;

public class TestShaderGUI : BaseShaderGUI
{
    public static readonly string QueueControlProperty = "_QueueControl";

    MaterialProperty[] properties;
    /// <summary>
    /// 全体の描画
    /// </summary>
    /// <param name="materialEditor"></param>
    /// <param name="properties"></param>
    public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties)
    {
        this.properties = properties;
        var targetMat = materialEditor.target as Material;
        if (!targetMat) return;

        //BaseShaderGUIでDrawSurfaceOptionsとDrawSurfaceInputsとDrawAdvancedOptionsが呼ばれる
        base.OnGUI(materialEditor, properties);
    }

    /*/Litなら追加させる
    public MaterialProperty workflowMode;

    MaterialProperty[] properties;
    public override void FindProperties(MaterialProperty[] properties)
    {
        // save off the list of all properties for shadergraph
        this.properties = properties;

        var material = materialEditor?.target as Material;
        if (material == null)
            return;

        base.FindProperties(properties);
        workflowMode = BaseShaderGUI.FindProperty("_WorkflowMode", properties, false);
    }
    */

    /// <summary>
    /// SurfaceInputsの描画
    /// </summary>
    /// <param name="material"></param>
    public override void DrawSurfaceInputs(Material material)
    {

    }

    /// <summary>
    /// SurfaceOptionsの描画
    /// </summary>
    /// <param name="material"></param>
    public override void DrawSurfaceOptions(Material material)
    {
        /*
            Litなら追加させる
        if (material == null)
            throw new ArgumentNullException("material");

        // Use default labelWidth
        EditorGUIUtility.labelWidth = 0f;

        // Detect any changes to the material
        if (workflowMode != null)
            DoPopup(LitGUI.Styles.workflowModeText, workflowMode, Enum.GetNames(typeof(LitGUI.WorkflowMode)));
        */
        base.DrawSurfaceOptions(material);
      
    }
    /// <summary>
    /// AdvancedOptionsの描画
    /// </summary>
    /// <param name="material"></param>
    public override void DrawAdvancedOptions(Material material)
    {
        //queue control の描画
        DoPopup(Styles.queueControl, queueControlProp, Styles.queueControlNames);
        if (material.HasProperty(QueueControlProperty) && material.GetFloat(QueueControlProperty) == (float)UnityEditor.BaseShaderGUI.QueueControl.UserOverride)
            materialEditor.RenderQueueField();
        //Sorting PriorityとEnableGPUInstancingの描画
        base.DrawAdvancedOptions(material);
        //DoubleSidedGlobal Illuminationの描画
        materialEditor.DoubleSidedGIField();
        //Litなら追加させる
        //materialEditor.LightmapEmissionFlagsProperty(0, enabled: true, ignoreEmissionColor: true);
    }
}
#endif

上記のような処理にするとなにもプロパティを追加してない初期の表示状態にできます。

追加したプロパティを表示させる

追加したプロパティを表示するにはFindPropertyでプロパティを取得してShaderPropertyで表示することができます。

    /// <summary>
    /// SurfaceInputsの描画
    /// </summary>
    /// <param name="material"></param>
    public override void DrawSurfaceInputs(Material material)
    {
        //ShaderGraphで設定したプロパティのReferenceを引数として渡す
        var colorProperty = FindProperty("_Color", properties);
        materialEditor.ShaderProperty(colorProperty, colorProperty.displayName);
    }

完成

適当に表示を変更させてみました。

#if UNITY_EDITOR
using UnityEngine;
using UnityEditor;//ShaderGUIで使用
using System.Collections.Generic;

public class TestShaderGUI : BaseShaderGUI
{
    public static readonly string QueueControlProperty = "_QueueControl";

    MaterialProperty[] properties;
    /// <summary>
    /// 全体の描画
    /// </summary>
    /// <param name="materialEditor"></param>
    /// <param name="properties"></param>
    public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties)
    {
        this.properties = properties;
        var targetMat = materialEditor.target as Material;
        if (!targetMat) return;

        EditorGUILayout.HelpBox("TestShaderGUIで拡張されています", MessageType.Info, true);
        EditorGUILayout.Space();

        //BaseShaderGUIでDrawSurfaceOptionsとDrawSurfaceInputsとDrawAdvancedOptionsが呼ばれる
        base.OnGUI(materialEditor, properties);
    }

    /*/Litなら追加させる
    public MaterialProperty workflowMode;

    MaterialProperty[] properties;
    public override void FindProperties(MaterialProperty[] properties)
    {
        // save off the list of all properties for shadergraph
        this.properties = properties;

        var material = materialEditor?.target as Material;
        if (material == null)
            return;

        base.FindProperties(properties);
        workflowMode = BaseShaderGUI.FindProperty("_WorkflowMode", properties, false);
    }
    */

    /// <summary>
    /// SurfaceInputsの描画
    /// </summary>
    /// <param name="material"></param>
    public override void DrawSurfaceInputs(Material material)
    {
        // ラベル(太字)
        GUILayout.Label("追加したプロパティ", EditorStyles.boldLabel);
        //ShaderGraphで設定したプロパティのReferenceを引数として渡す
        var colorProperty = FindProperty("_Color", properties);
        materialEditor.ShaderProperty(colorProperty, colorProperty.displayName);
    }

    /// <summary>
    /// SurfaceOptionsの描画
    /// </summary>
    /// <param name="material"></param>
    public override void DrawSurfaceOptions(Material material)
    {
        /*
            Litなら追加させる
        if (material == null)
            throw new ArgumentNullException("material");

        // Use default labelWidth
        EditorGUIUtility.labelWidth = 0f;

        // Detect any changes to the material
        if (workflowMode != null)
            DoPopup(LitGUI.Styles.workflowModeText, workflowMode, Enum.GetNames(typeof(LitGUI.WorkflowMode)));
        */
        base.DrawSurfaceOptions(material);
      
    }
    /// <summary>
    /// AdvancedOptionsの描画
    /// </summary>
    /// <param name="material"></param>
    public override void DrawAdvancedOptions(Material material)
    {
        //queue control の描画
        DoPopup(Styles.queueControl, queueControlProp, Styles.queueControlNames);
        if (material.HasProperty(QueueControlProperty) && material.GetFloat(QueueControlProperty) == (float)UnityEditor.BaseShaderGUI.QueueControl.UserOverride)
            materialEditor.RenderQueueField();
        //Sorting PriorityとEnableGPUInstancingの描画
        base.DrawAdvancedOptions(material);
        //DoubleSidedGlobal Illuminationの描画
        materialEditor.DoubleSidedGIField();
        //Litなら追加させる
        //materialEditor.LightmapEmissionFlagsProperty(0, enabled: true, ignoreEmissionColor: true);
    }
}
#endif

変更できる内容はこちらを参考にしてください

docs.unity3d.com

他にInspectorを拡張する方法として下記アセットがあります