【Unity】UI Toolkitの要素内でIMGUIを使えるIMGUI Containerの使い方

UnityのUI Toolkitの要素内でIMGUIを使えるIMGUI Containernの使い方についてまとめました。

Unity 2022.2.17

IMGUI Containerとは?

IMGUIContainerを使うと、UI Toolkitのレイアウトシステムでレイアウトを行ったVisual Elementの中にIMGUIGUIを描画することができます。
UI Toolkitが出てくる前はエディタのコードはIMGUIで書いていたため、これはその互換性を保つための機能であると言えます。

実装

IMGUIContainerは以下のように使います。

using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;

public sealed class Example : EditorWindow
{
    private void CreateGUI()
    {
        // 適当に上部にVisualElementを置いておく
        var topLabel = new Label("This is UI Toolkit");
        SetBorder(topLabel, 1.0f, Color.blue);
        rootVisualElement.Add(topLabel);

        // IMGUI Containerを配置
        {
            var imguiContainer = new IMGUIContainer();
            imguiContainer.style.flexGrow = 1.0f;
            SetBorder(imguiContainer, 1.0f, Color.red);
            
            imguiContainer.onGUIHandler = () =>
            {
                // onGUIHandlerの中にIMGUIを書く
                Debug.Log("IMGUIContainer");
                GUILayout.Label("This is IMGUI");
            };
            
            // cullingEnabledをtrueにすると、このIMGUIContainerがPanelの外にあるときにはonGUIHandlerが呼ばれない
            // デフォルトはfalse
            //imguiContainer.cullingEnabled = true;
            
            // IMGUIのレイアウトにDirtyフラグを立てる
            //imguiContainer.MarkDirtyLayout();
            
            // 現状はEditorのみのサポートだが、いずれはPlayerで使う場合にはcontextTypeをPlayerにする必要がありそう
            //imguiContainer.contextType = ContextType.Editor;
            
            rootVisualElement.Add(imguiContainer);
        }
        
        // 適当に下部にVisualElementを置いておく
        var bottomLabel = new Label("This is UI Toolkit");
        SetBorder(bottomLabel, 1.0f, Color.blue);
        rootVisualElement.Add(bottomLabel);
    }
    
    private static void SetBorder(VisualElement element, StyleFloat width, StyleColor color)
    {
        element.style.borderBottomColor = color;
        element.style.borderLeftColor = color;
        element.style.borderRightColor = color;
        element.style.borderTopColor = color;
        element.style.borderBottomWidth = width;
        element.style.borderLeftWidth = width;
        element.style.borderRightWidth = width;
        element.style.borderTopWidth = width;
    }

    [MenuItem("Window/Example")]
    private static void Open()
    {
        GetWindow<Example>();
    }
}

結果

Window > Exampleから前節で作ったウィンドウを開くと以下の結果が得られます。

結果

VisualElement内でIMGUIによる描画ができていることを確認できました。

参考

docs.unity.cn