17
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

グレンジAdvent Calendar 2020

Day 20

【Unity:エディタ拡張】エディタでデータリスト表示をしてみよう

Last updated at Posted at 2020-12-19

グレンジ Advent Calendar 2020 20日目の記事担当kenjiです
クライアントエンジニアやってます

前にこんな記事を書いたんですが
【Unity:エディタ拡張】Unityでエディタ拡張を始めよう
そこからもう少しエディタ拡張(主にレイアウトについて)に触れてみようと思います

実用的かは別として…
僕がエディタでデータリストを管理するときによくやる手法を書きます
やり方は色々ありますが、極力シンプルな設計でやってみます

Unityバージョン:2020.1.x

1. EditorWindowスクリプトの作成

とりあえずエディタウィンドウ作成します

EditorWindowSample.cs
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

public class EditorWindowSample : EditorWindow
{
    [MenuItem("Editor/Sample")]
    private static void Create()
    {
        GetWindow<EditorWindowSample>("サンプル");
    }
}

Unityの上部メニュー「Editor > Sample」からウィンドウが開きます
qiita_001.png

2. ScriptableObjectスクリプトの作成

次にデータ用のスクリプトを作ります
パラメータは適当です

ScriptableObjectSample.cs
using System;
using UnityEngine;

[Serializable]
public class ScriptableObjectSample : ScriptableObject
{
	[SerializeField]
	private int _sampleIntValue;
	[SerializeField]
	private float _sampleFloatValue;
	[SerializeField]
	private string _sampleStringValue;
}

3. レイアウトの骨組み

今回はレイアウトをスコープで2つに分割します
左にリスト、右に選択したデータのパラメータ
という感じでやってみます

エディタウィンドウのスクリプトに下記を追記します

EditorWindowSample.cs
public class EditorWindowSample : EditorWindow
{
	private Vector2 _dataScrollPosition;
	private Vector2 _parameterScrollPosition;

	...

	private void OnGUI()
	{
		using (new GUILayout.HorizontalScope())
		{
			UpdateLayoutData();
			UpdateLayoutParameter();
		}
	}

	private void UpdateLayoutData()
	{
		using (GUILayout.ScrollViewScope scroll = new GUILayout.ScrollViewScope(_dataScrollPosition, EditorStyles.helpBox, GUILayout.Width(150)))
		{
			_dataScrollPosition = scroll.scrollPosition;

			GUILayout.Label("data");
		}
	}
	private void UpdateLayoutParameter()
	{
		using (GUILayout.ScrollViewScope scroll = new GUILayout.ScrollViewScope(_parameterScrollPosition, EditorStyles.helpBox))
		{
			_parameterScrollPosition = scroll.scrollPosition;

			GUILayout.Label("parameter");
		}
	}
}

この時点でこんな感じのレイアウトになります
分かりやすいように一旦ラベル表示してます
qiita_002.png

4. データリストの表示

あとは各レイアウトを固めていくだけです
最初にデータリストからやってみます
仮で追加してたラベル表示は消しちゃってください

EditorWindowSample.cs
...

public class EditorWindowSample : EditorWindow
{
    private List<ScriptableObjectSample> _samples = new List<ScriptableObjectSample>();
    private ScriptableObjectSample _selectSample = null;

    ...
    
    private void UpdateLayoutData()
    {
        using (GUILayout.ScrollViewScope scroll = new GUILayout.ScrollViewScope(_dataScrollPosition, EditorStyles.helpBox, GUILayout.Width(150)))
        {
            _dataScrollPosition = scroll.scrollPosition;

            // メニュー追加
            GenericMenu menu = new GenericMenu();
            if (Event.current.type == EventType.ContextClick && Event.current.button == 1)
            {
                menu.AddItem(new GUIContent("AddSample"), false, () =>
                {
                    _samples.Add(CreateInstance<ScriptableObjectSample>());
                    _selectSample = _samples[_samples.Count - 1];
                });
            }

            // データリスト
            for (int i = 0; i < _samples.Count; i++)
            {
                GUI.backgroundColor = (_samples[i] == _selectSample ? Color.cyan : Color.white);
                if (GUILayout.Button($"{i}:sample"))
                {
                    _selectSample = _samples[i];
                }
                GUI.backgroundColor = Color.white;
            }

            // メニュー表示
            if (menu.GetItemCount() > 0)
            {
                menu.ShowAsContext();
                Event.current.Use();
            }
        }
    }
}

今回は右クリックからのメニュー追加をやってみました
データレイアウト内で右クリックして「AddSample」を選択するとデータが追加されるかと思います
これだけでもエディタ感でますよね
qiita_003.png

5. パラメータの表示

次はパラメータの表示です
ここでは選択中のデータのパラメータを表示します

EditorWindowSample.cs
...

public class EditorWindowSample : EditorWindow
{
    private void UpdateLayoutParameter()
    {
        using (GUILayout.ScrollViewScope scroll = new GUILayout.ScrollViewScope(_parameterScrollPosition, EditorStyles.helpBox))
        {
            _parameterScrollPosition = scroll.scrollPosition;

            if (_selectSample)
			{
				Editor.CreateEditor(_selectSample).DrawDefaultInspector();
			}
		}
	}
}

単純にデータのデフォルトインスペクター呼ぶだけです
簡単でした

qiita_004.png

おまけ

ここまでやってきてデータの追加はできるんですけど
削除できないじゃんってなるので削除も右クリックメニューでできるようにしてみます
ボタン押したときの処理に右クリックだった場合の処理を追加します

EditorWindowSample.cs
...

public class EditorWindowSample : EditorWindow
{
    ...
    
    private void UpdateLayoutData()
    {
        ...
            if (GUILayout.Button($"{i}:sample"))
            {
                _selectSample = _samples[i];

                // メニュー追加
                if (Event.current.button == 1)
                {
                    int index = i;
                    menu.AddItem(new GUIContent("Remove"), false, () =>
                    {
                        _samples.Remove(_samples[index]);
                        _selectSample = (_selectSample == _samples[index] ? null : _selectSample);
                    });
                }
            }
        ...
    }

追加の場合と基本同じですね
qiita_005.png

まとめ

今回はシンプルな例でしたが、エディタ拡張って機能追加や使いやすさを突き詰めていくと複雑な設計になったり可読性が悪くなったりするんですよね
地道なんですが、ハマる人にはハマる作業だと思うので
ちょっと面白いかもっと思った方はこれを機にもっと機能拡張をしてみてはどうでしょうか

17
17
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
17
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?