【Untiy】ChatGPTでGenericMenuのサンプルコードを作る

投稿者: | 2023-06-02

ChatGPTに、GenericMenuのサンプルコードを作ってもらいました。

スクリプト

using UnityEngine;
using UnityEditor;

public class GenericMenuExample : EditorWindow
{
    Color backgroundColor = Color.white;
    Color textColor = Color.black;
    Rect buttonRect;

    [MenuItem("Example/Show Window")]
    static void ShowWindow()
    {
        EditorWindow.GetWindow(typeof(GenericMenuExample));
    }

    void OnGUI()
    {
        EditorGUI.DrawRect(new Rect(0, 0, maxSize.x, maxSize.y), backgroundColor);
        GUI.color = textColor;
        GUILayout.Label("Current Background Color", EditorStyles.boldLabel);
        backgroundColor = EditorGUILayout.ColorField(backgroundColor);

        GUI.color = Color.black;
        GUILayout.Label("Current Text Color", EditorStyles.boldLabel);
        textColor = EditorGUILayout.ColorField(textColor);

        GUI.color = Color.white;
        if (Event.current.type == EventType.Repaint) buttonRect = GUILayoutUtility.GetLastRect();
        
        if (GUILayout.Button("Open Color Menu"))
        {
            //buttonRect = GUILayoutUtility.GetLastRect();

            GenericMenu menu = new GenericMenu();

            // Set allowDuplicateNames property to true
            menu.allowDuplicateNames = true;

            // AddItem method to add "Toggle Color" actions which toggle background color and text color between red and white
            menu.AddItem(new GUIContent("Background Color/Toggle Color"), false, () =>
            {
                backgroundColor = backgroundColor == Color.white ? Color.red : Color.white;
            });
            menu.AddItem(new GUIContent("Text Color/Toggle Color"), false, () =>
            {
                textColor = textColor == Color.white ? Color.red : Color.white;
            });

            // AddDisabledItem method
            menu.AddDisabledItem(new GUIContent("Disabled Item"));

            // AddSeparator method
            menu.AddSeparator("");

            // GetItemCount method
            Debug.Log("Item count: " + menu.GetItemCount());

            // DropDown method
            menu.DropDown(buttonRect);
        }

        if (Event.current.type == EventType.ContextClick)
        {
            buttonRect = GUILayoutUtility.GetLastRect();

            GenericMenu menu = new GenericMenu();

            // Set allowDuplicateNames property to true
            menu.allowDuplicateNames = true;

            // AddItem method to add "Toggle Color" actions which toggle background color and text color between red and white
            menu.AddItem(new GUIContent("Background Color/Toggle Color"), false, () =>
            {
                backgroundColor = backgroundColor == Color.white ? Color.red : Color.white;
            });
            menu.AddItem(new GUIContent("Text Color/Toggle Color"), false, () =>
            {
                textColor = textColor == Color.white ? Color.red : Color.white;
            });

            // AddDisabledItem method
            menu.AddDisabledItem(new GUIContent("Disabled Item"));

            // AddSeparator method
            menu.AddSeparator("");

            // GetItemCount method
            Debug.Log("Item count: " + menu.GetItemCount());

            // ShowAsContext method
            menu.ShowAsContext();
        }
    }
}

エディタウィンドウを表示する

UnityでEditorフォルダに上記のスクリプトを作成します。

メインメニューの Example > Show Window でエディタウィンドウが開きます。

ボタンをクリックすると、DropDownメソッドでボタンの下にメニューが表示され、エディタウィンドウを右クリックするとマウスの位置にメニューが表示されます。

どちらのメニューでも同じ処理を行います。Background Color > Toggle Color で背景色が変わり、Text Color > Toggle Color で文字色が変わります。

ChatGPT

ChatGPTには、UnityマニュアルのGenericMenuのページのサンプルコード以外の説明部分をコピペして指示を送りました。サンプルコードを送った場合、それとほとんど同じコードを出力しました。

あなたは経験豊富なプロのゲームプログラマーであり、独創的なUnityのサンプルコードを作成中です。

以下のドキュメントの内容を学習するための、実用的なサンプルスクリプトを作ってください。
必ずすべてのプロパティとすべてのPublic Methodsを使ってください。

# サンプルコード以外の部分をコピペ

必ず答えの前に質問をしなければいけません。
質問者が何を求めているのか、より明確にするためです。
理解されましたか?

すると、ChatGPTから質問されます。

はい、理解しました。まずは、質問させていただきます。

  1. このサンプルスクリプトは、特定のゲームオブジェクトに関連付けられるものでしょうか?それとも特定のエディタウィンドウ、またはシーンで使用するためのものでしょうか?
  2. “AddItem”メソッドで追加されるアイテムは、具体的に何を表していますか?例えば、特定のゲームアクション、スクリプト、またはその他の何かを表していますか?
  3. このコードが使用されるコンテキストにおいて、どのような状況で項目が無効化(”AddDisabledItem”メソッドの使用)されるべきでしょうか?
  4. “allowDuplicateNames”プロパティがtrueの場合、同名のメニューアイテムにはそれぞれ異なる動作が割り当てられるべきでしょうか、それとも同じ動作を持つべきでしょうか?
以上の質問の回答を元に、最適なUnityのサンプルコードを作成します。

少し具体的に条件を付けてみました。

1、これは特定のエディタウィンドウで使用するものです。
2、AddItemで追加されるアイテムもあなたが考えてください。
3、AddDisabledItemが使用される状況もおまかせします。ただし、同じアイテムが無効化される状況とそうでない状況を作ってください。
4、allowDuplicateNamesをtrueにして、異なる動作を割当ててください。

すると、Debug.Logを表示するスクリプトが送られました。

using UnityEngine;
using UnityEditor;

public class CustomEditorWindow : EditorWindow
{
    private GenericMenu menu;

    [MenuItem("Window/Custom Editor Window")]
    static void Init()
    {
        CustomEditorWindow window = (CustomEditorWindow)EditorWindow.GetWindow(typeof(CustomEditorWindow));
        window.Show();
    }

    private void OnGUI()
    {
        if (GUILayout.Button("Open Menu"))
        {
            ShowGenericMenu();
        }
    }

    void ShowGenericMenu()
    {
        menu = new GenericMenu();
        menu.allowDuplicateNames = true;

        menu.AddItem(new GUIContent("Action1"), false, ActionCallback, "Action1 Enabled");
        menu.AddItem(new GUIContent("Action2"), false, ActionCallback, "Action2 Enabled");

        if (Random.value > 0.5f) // Arbitrary condition to simulate different situations.
        {
            menu.AddDisabledItem(new GUIContent("Action3"));
        }
        else
        {
            menu.AddItem(new GUIContent("Action3"), false, ActionCallback, "Action3 Enabled");
        }

        menu.AddSeparator("");
        menu.AddItem(new GUIContent("Action1"), false, ActionCallback, "Action1 Enabled with different behaviour");

        Debug.Log("Number of items in the menu: " + menu.GetItemCount());

        menu.ShowAsContext();
    }

    void ActionCallback(object obj)
    {
        Debug.Log("Selected: " + obj);
    }
}

Action3が無効化するかどうかは、ボタンをクリックしたときにランダムで決まるようです。

また、はじめのAction1では「Selected: Action1 Enabled」、2つ目のAction1では「Selected: Action1 Enabled with different behaviour」と表示されます。DropDownメソッドは使われていないようです。

「具体的な例を使った独創的なサンプルスクリプトを作ってください」などに指示を変えると色を変えるサンプルコードが出ました。

さらに具体的な条件を付けてみました。

一つのメニューの中に、同じ名前のアイテムを一組は作ってください。同じ名前のアイテムにそれぞれ異なる処理が割当てられています。2つの処理はアイテムの名前の意味と関連のあるものにしてください。 それ以外にアイテムを作っても良いです。 DropDownメソッドとShowAsContextを両方使ってください。

少し修正してはじめのスクリプトが得られました。

スクリプト詳細

EditorWindow.GetWindowメソッドでこのエディタウィンドウを表示できます。それを呼ぶ静的メソッドにMenuItem属性を付けてメインメニューから実行できるようにしています。

using UnityEngine;
using UnityEditor;

public class GenericMenuExample : EditorWindow
{
    Color backgroundColor = Color.white;
    Color textColor = Color.black;
    Rect buttonRect;

    [MenuItem("Example/Show Window")]
    static void ShowWindow()
    {
        EditorWindow.GetWindow(typeof(GenericMenuExample));
    }

背景色や文字色、ボタンの矩形範囲のフィールドがあります。

OnGUIメソッドにGUIを実装します。まずEditorGUI.DrawRectメソッドで背景色で塗りつぶした矩形を表示します。サイズはEditorWindow.maxSizeにしています、これはエディタウィンドウの最大サイズなので、ウィンドウ全体が塗りつぶされます。

    void OnGUI()
    {
        EditorGUI.DrawRect(new Rect(0, 0, maxSize.x, maxSize.y), backgroundColor);

EditorWindow.maxSizeは通常(4000,4000)で、変更もできます。実際には100くらいまでしか小さくなりませんでした。

ボタンやフィールドの後に記述すると、それらが上から塗りつぶされて見えなくなります。

GUI.colorでテキストや背景に影響するグローバルな色を textColor に設定して、ラベルを表示します。

        GUI.color = textColor;
        GUILayout.Label("Current Background Color", EditorStyles.boldLabel);

これで「Current Background Color」の文字が textColor フィールドに設定された色で表示されます。

背景色のフィールドを表示します。クリックしてカラーピッカーから色を変更できます。

        backgroundColor = EditorGUILayout.ColorField(backgroundColor);

同様に、色を黒に戻してラベルを表示し、文字色のフィールドを表示します。

        GUI.color = Color.black;
        GUILayout.Label("Current Text Color", EditorStyles.boldLabel);
        textColor = EditorGUILayout.ColorField(textColor);

その後ボタンを表示しますが、文字色が黒だとボタン上の文字が見にくいので自分で修正して白に戻しています。

GUI.color = Color.white;

また、ボタンの矩形範囲が取得できていなかったのでそれも追記しました。

        if (Event.current.type == EventType.Repaint) buttonRect = GUILayoutUtility.GetLastRect();
修正前

ボタンを表示し、クリックするとGenericMenuのインスタンスを作ります。

        if (GUILayout.Button("Open Color Menu"))
        {
            //buttonRect = GUILayoutUtility.GetLastRect();

            GenericMenu menu = new GenericMenu();

GenericMenu.allowDuplicateNamesをtrueにして、同じ名前のアイテムが複数作れるようにし、GenericMenu.AddItemメソッドでアイテムを2つ追加しています。処理はラムダ式で記述しています。

            // Set allowDuplicateNames property to true
            menu.allowDuplicateNames = true;

            // AddItem method to add "Toggle Color" actions which toggle background color and text color between red and white
            menu.AddItem(new GUIContent("Background Color/Toggle Color"), false, () =>
            {
                backgroundColor = backgroundColor == Color.white ? Color.red : Color.white;
            });
            menu.AddItem(new GUIContent("Text Color/Toggle Color"), false, () =>
            {
                textColor = textColor == Color.white ? Color.red : Color.white;
            });

アイテムの名前は「/」で区切られていて、実際には末尾だけが同じなので、GenericMenu.allowDuplicateNamesをtrueにする必要はないようです。同じ名前にしてfalseにすると、はじめの方しか表示されなくなります。

            menu.allowDuplicateNames = false;

            // AddItem method to add "Toggle Color" actions which toggle background color and text color between red and white
            menu.AddItem(new GUIContent("Toggle Color"), false, () =>
            {
                backgroundColor = backgroundColor == Color.white ? Color.red : Color.white;
            });
            menu.AddItem(new GUIContent("Toggle Color"), false, () =>
            {
                textColor = textColor == Color.white ? Color.red : Color.white;
            });

GenericMenu.AddDisabledItemメソッドでは、グレーアウトされて選択不可能なアイテムを表示できます。「Disabled Item」という名前の項目です。

            // AddDisabledItem method
            menu.AddDisabledItem(new GUIContent("Disabled Item"));

GenericMenu.AddSeparatorメソッドで区切り文字を追加しています。引数に空文字を渡しているので、最上位レベルに区切り文字が入ります。

            // AddSeparator method
            menu.AddSeparator("");

「Text Color/」を渡すと、Text Colorの項目を開いたときに区切り文字が表示されます。

            menu.AddItem(new GUIContent("Background Color/Toggle Color"), false, () =>
            {
                backgroundColor = backgroundColor == Color.white ? Color.red : Color.white;
            });

            menu.AddSeparator("Text Color/");

            menu.AddItem(new GUIContent("Text Color/Toggle Color"), false, () =>
            {
                textColor = textColor == Color.white ? Color.red : Color.white;
            });

GenericMenu.GetItemCountメソッドでメニューに表示されている項目数を取得できます。これは区切り文字もカウントしているようです。

            // GetItemCount method
            Debug.Log("Item count: " + menu.GetItemCount());

区切り文字をコメントアウトすると数が減ります。

最後に、GenericMenu.DropDownメソッドでメニューを表示します。引数にボタンのRectを渡すと、ボタンの下に表示されます。

右クリックをすると、処理中のイベントタイプが EventType.ContextClick になります。

        if (Event.current.type == EventType.ContextClick)
        {
            // ...

            // ShowAsContext method
            menu.ShowAsContext();
        }
    }
}

表示するものは同じですが、GenericMenu.ShowAsContextメソッドを使って、右クリックしたときのマウスの位置にメニューを表示します。

これで、ChatGPTにGenericMenuのサンプルコードを書いてもらって、エディタウィンドウを表示できました。

コメントを残す

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