【Unity】Material Editorでシーンビューにハンドルを表示する

投稿者: | 2023-12-26

マテリアルエディタでシーンビューにハンドルを表示して、値をセットしてみました。

シェーダー

フルスクリーンカスタムパスで、プロパティに2つの位置を定義して、ワールド空間位置との距離を計算します。

        float depth = LoadCameraDepth(varyings.positionCS.xy);
        PositionInputs posInput = GetPositionInput(varyings.positionCS.xy, _ScreenSize.zw, depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_V);

        // 中心からの距離
        float dist = distance(posInput.positionWS, _CenterPos - _WorldSpaceCameraPos);
        float dist2 = distance(posInput.positionWS, _CenterPos2 - _WorldSpaceCameraPos);

step関数を使って、球の内側は白、外側は黒にします。

        // 球
        float sphere = 1 - step(_Radius,  dist);
        float sphere2 = 1 - step(_Radius, dist2);
        //float sphere2 = step(0, _Radius - dist2);

排他的論理和を計算して色にかけてみました。

        // 合成する
        float result = frac(sphere * 0.5 + sphere2 * 0.5) * 2;

        return result * _Color;

このシェーダーを設定したマテリアルを作成して、カスタムパスにアタッチしました。

Material Editor

Editorフォルダに新規C#スクリプトを作成して、MaterialEditorクラスを継承させます。

using UnityEngine;
using UnityEditor;

public class HandleTestMaterialEditor : MaterialEditor
{
    private new void OnEnable()
    {
        // シーンビューのイベントを購読
        SceneView.duringSceneGui += OnSceneGUI;
    }
    private new void OnDisable()
    {
        // イベントの購読解除
        SceneView.duringSceneGui -= OnSceneGUI;
    }
    private void OnSceneGUI(SceneView sv)
    {
        // マテリアルを取得
        var mat = (Material)target;

        if (mat == null) return;

        // 値を取得
        Vector3 pos = mat.GetVector("_CenterPos");
        Vector3 pos2 = mat.GetVector("_CenterPos2");

        // GUI要素の変更をチェック開始
        EditorGUI.BeginChangeCheck();

        // ハンドルを表示
        pos = Handles.PositionHandle(pos, Quaternion.identity);
        pos2 = Handles.PositionHandle(pos2, Quaternion.identity);

        // ハンドルが操作されたとき
        if (EditorGUI.EndChangeCheck())
        {
            // 元に戻せるようにする
            Undo.RecordObject(target, "Move point");

            // 値をセット
            mat.SetVector("_CenterPos", pos);
            mat.SetVector("_CenterPos2", pos2);
        }

    }
}

カスタムハンドルを実装するために、シーンビューのイベントを購読/解除しています。

    private new void OnEnable()
    {
        // シーンビューのイベントを購読
        SceneView.duringSceneGui += OnSceneGUI;
    }
    private new void OnDisable()
    {
        // イベントの購読解除
        SceneView.duringSceneGui -= OnSceneGUI;
    }

OnSceneGUIメソッドでは、マテリアルとプロパティの値を取得します。

    private void OnSceneGUI(SceneView sv)
    {
        // マテリアルを取得
        var mat = (Material)target;

        if (mat == null) return;

        // 値を取得
        Vector3 pos = mat.GetVector("_CenterPos");
        Vector3 pos2 = mat.GetVector("_CenterPos2");

ハンドルの変更のチェックを開始して、ハンドルを表示します。

        // GUI要素の変更をチェック開始
        EditorGUI.BeginChangeCheck();

        // ハンドルを表示
        pos = Handles.PositionHandle(pos, Quaternion.identity);
        pos2 = Handles.PositionHandle(pos2, Quaternion.identity);

変更があればUndoできるようにして、値をセットしています。

        // ハンドルが操作されたとき
        if (EditorGUI.EndChangeCheck())
        {
            // 元に戻せるようにする
            Undo.RecordObject(target, "Move point");

            // 値をセット
            mat.SetVector("_CenterPos", pos);
            mat.SetVector("_CenterPos2", pos2);
        }

シェーダーでマテリアルエディタのクラス名を指定します。


        // ...
        CustomEditor "HandleTestMaterialEditor"
}

マテリアルを選択

Projectウィンドウでマテリアルを選択すると、シーンビューにハンドルが表示されました。

コメントを残す

メールアドレスが公開されることはありません。