LoginSignup
1
0

【Unity】SceneView上のカーソル位置のオブジェクトのマテリアルを変えるEditor拡張

Posted at

概要

SceneView上のカーソル位置のオブジェクトを取得し、そのオブジェクトのマテリアルを複数の任意のマテリアルに変更できるようにする。
ショートカットをいくつか用意し、それぞれにマテリアルを割り当てて、そのマテリアルに変えれるようにする。
MaterialChanger.gif

Windowの作成

変更したいマテリアルを新しいタブから設定できるようにします。

MaterialChanger.cs
using UnityEditor;
using UnityEngine;

public class MaterialChanger : EditorWindow
{
    static Material _materialQ;
    static Material _materialE;
    static Material _materialR;

    [MenuItem("Tools/MaterialChanger/MaterialChanger Window")]
    private static void Open()
    {
        MaterialChanger materialChanger = GetWindow<MaterialChanger>();
        materialChanger.Show();
    }

    private void OnGUI()
    {
        _materialQ = EditorGUILayout.ObjectField("Material Q", _materialQ, typeof(Material), false) as Material;
        _materialE = EditorGUILayout.ObjectField("Material E", _materialE, typeof(Material), false) as Material;
        _materialR = EditorGUILayout.ObjectField("Material R", _materialR, typeof(Material), false) as Material;
    }
}

新しいWindowを開く関数Openを定義し、Unityのツールバーから実行できるようにします。
OnGUIでWindowを編集します。
EditorGUILayout.ObjectFieldでオブジェクトの取得、表示をします。
QERをショートカットにしたのでこの3つの変数名になっている。
image.png

image.png
ツールバーにメニューが表示され、Windowが開ける。

マテリアル変更処理

SceneView上のカーソル位置のオブジェクトを取得

[InitializeOnLoadMethod]でSceneView上のOnGUIを登録することが出来る。
引数SceneViewの関数を登録し、Eventからマウスの位置を取得する。

        static Vector2 _mousePos;

        [InitializeOnLoadMethod]
        private static void Initialize()
        {
            SceneView.duringSceneGui += SceneViewOnGUI;
        }

        static void SceneViewOnGUI(SceneView sceneView)
        {
            Event e = Event.current;
            _mousePos = e.mousePosition;
        }

マテリアル変更

HandleUtility.PickGameObjectでマウス位置のオブジェクト取得。
RenderersharedMaterialからマテリアルの変更

        static void ChangingMaterialQ()
        {
            var picked = HandleUtility.PickGameObject(_mousePos, false);

            if (picked && picked.TryGetComponent(out Renderer renderer))
            {
                renderer.sharedMaterial = _materialQ;
            }
        }

ショートカットで呼び出す

        [MenuItem("Tools/MaterialChanger/Change Material on E #e")] // Shift+E
        static void ChangingMaterialE()
        {
            // 中略
        }
        
        [MenuItem("Tools/MaterialChanger/Change Material on R #&r")] // Shift+Alt+R
        static void ChangingMaterialR()
        {
            // 中略
        }

新しいアイテムメニューを追加します。追加する項目の文字列の最後の記号でショートカットを設定できます。
%でCtrl、#でShift、&でAltを指定できます。
image.png
アイテムメニューに追加することでEditorからもショートカットを変更できます。
image.png
これで使うことが出来ます。

注意点

エラーが出る

image.png
詳しい理由はわからなかったのですがおそらくHandleUtility.PickGameObjectをOnGUI外で使ったからだと思います。SceneViewOnGUI内でキー判定して呼び出したらエラーはなくなりましたが、Unityのショートカットとして使用できなくなります。エラーが出ても問題なく使用できるので僕は無視して使いました。

        static void SceneViewOnGUI(SceneView sceneView)
        {
            Event e = Event.current;
            _mousePos = e.mousePosition;

            if (e.keyCode == KeyCode.Q)
            {
                ChangingMaterialQ(); // ここで呼び出す
            }
        }

変更が保存されない

これを使って変更を加えても変更として認識されず、保存されません。これは現在のシーンを右クリックなどで直接SaveSceneすると保存されます。また、プレハブの変更はApplyAllでも保存できます。
image.png

参考

1
0
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
1
0