Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

Unityエディタ拡張作ってみた advent 2018

More than 1 year has passed since last update.

はじめに

作ってみたエディタ拡張をいろいろと紹介したいと思います。
UniRxでObservableにしてみたEditorWindowやSerializeFieldに関するものなどいろいろ作ってみたのでどうぞみてみてください。

環境

  • Unity2018.3.0f2
    • Scripting Runtime Version (.NET 4.X Equivalent)
  • UniRx ver6.2.2

作ったみたリスト

今回作ってみたものリストとなります。
作ったコードは個人のGitHubGistにて公開しましたのでご自由にご利用ください。

解説

作ってみたものを解説いたします。

UniRxでエディターウィンドウをObservableにしてみた

コード一部略

public abstract class ObservableWindowBase : EditorWindow
{
    Subject<Unit> update;
    Container Root = new Container();

    public IObservable<Unit> UpdateAsObservable()
    {
        return update ?? (update = new Subject<Unit>());
    }

    public TElement AddElement<TElement>(TElement element) where TElement : IElement
    {
        return Root.AddElement<TElement>(element);
    }

    void Update()
    {
        if (update != null) { update.OnNext(Unit.Default); }
    }

    void OnGUI()
    {
        (Root as IElement).Draw();
    }
}
public class ObservableTestEditorWindow : ObservableWindowBase
{
    [MenuItem("Window/ObservableTestEditorWindow")]
    static void Init()
    {
        GetWindow<ObservableTestEditorWindow>();
    }

    Toggle updateToggle;

    void OnEnable()
    {
        new Button(this, "label1")
            .OnClickAsObservable()
            .Subscribe(_ => { Debug.Log("clicked button 1"); });

        new Button(this, "label2")
            .OnClickAsObservable()
            .Subscribe(_ => { Debug.Log("clicked button 2"); });

        updateToggle = new Toggle(this, false, "isUpdate");
        updateToggle.OnValueChangedAsObservable().Subscribe(v =>
        {
            Debug.Log("on value changed to:" + v);
        });

        UpdateAsObservable()
            .Where(x => updateToggle.RValue.Value)
            .Subscribe(_ =>
        {
            Debug.Log("Update...");
        });
    }
}
public class Button : IElement
{
    Subject<Unit> onClick;
    string label;

    public Button(ObservableWindowBase window, string label)
    {
        window.AddElement(this);
        this.label = label;
    }

    void IElement.Draw()
    {
        if (GUILayout.Button(label)) onClick?.OnNext(Unit.Default);
    }

    public IObservable<Unit> OnClickAsObservable()
    {
        return onClick ?? (onClick = new Subject<Unit>());
    }
}

実際にObservableになっているのはEditorWindow.Updateのみですが、
UniRxのコードっぽく書けるようにできました。
しかしながら試しに作ってみた程度のものでございます。。

SerializeFieldをリフレクションでゲットしてnullならエラー

現在のシーンでSerializeFieldのオブジェクトがnullのものがあったらエラーを出します。

    // 必要なusing
    using UnityEngine;
    using UnityEditor;
    using System.Reflection;
    using System.Linq;

    [MenuItem("Test/SerializeField Null Check in this Scene")]
    static void SerializeFieldNullCheck()
    {
        foreach (var component in GameObject.FindObjectsOfType<Component>())
        {
            var fields = component.GetType()
                .GetFields(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy)
                .SelectMany(x => x.CustomAttributes.Where(t => t.AttributeType == typeof(SerializeField)).Select(_ => x));

            foreach (var field in fields)
            {
                var value = field.GetValue(component);
                UnityEngine.Assertions.Assert.IsNotNull(value, "Error! [SerializeField] " + field.Name + " is null !!");
            }
        }
    }

リフレクションでSerializeFieldをゲットする

FieldInfoCustomAttributesAttributeTypeがSerializeFieldなものでとってこれます。
そのフィールドのGetValueの値がnullだったらエラー表示する、という感じにすればOKです。

用途

外れてはいけないSerializeFieldがいつのまにか(誰かが気づかぬまま?!)外してしまっていることに気づかないことがあったとしても、上のようなテストコードを書いてCIするといいかも?!

SerializeFieldをリンクしてスクリプト生成ウィザード

スクリプトの生成とSerializeFieldのリンクを同時に行ってくれるスクリプト生成ウィザードです。
2018-12-20_01h49_24.png

Editorフォルダ以下に置くEditorのAssemblyDefinitionを右クリックメニューから作成できるようにするエディタ拡張

2018-12-15_22h05_12.png
EditorのAssemblyDefinitionを作成するときの手順が少し面倒だったため一発で作成できるのをつくってみました。

まとめ

いかがでしたでしょうか。
役に立ちそうなものがあれば幸いです。

gumi
Python、Erlang、Elixir などちょっと変わった技術でゲームをつくったりする会社。プログラマだけじゃなく、企画、デザイン、イラストなど開発全般揃ってます。
http://gu3.co.jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away