【Unity】ChatGPTにエディタ拡張のスクリプトを修正してもらう

投稿者: | 2023-05-23

ChatGPTに、カスタムエディタでシーンビューにバウンディングボックスを表示するのスクリプトを修正してもらいました。

このスクリプトでは、シーンに表示したバウンディングボックスの面を動かすと、反対側の面も自動で動き、センターの位置は変わりません。

これをChatGPTに修正してもらい、面を動かしたときに反対側の面は動かず、センターの位置が自動で変わるようにしてみました。

スクリプト

using UnityEngine;
using UnityEditor;

[CustomEditor(typeof(TestBounds))]
public class TestBoundsEditor : Editor
{
    void OnEnable()
    {
        SceneView.duringSceneGui += OnSceneGUI;
    }

    void OnDisable()
    {
        SceneView.duringSceneGui -= OnSceneGUI;
    }

    void OnSceneGUI(SceneView sv)
    {
        var t = (target as TestBounds);
        var bounds = t.bounds;

        EditorGUI.BeginChangeCheck();

        Vector3 centerPos = Handles.PositionHandle(bounds.center, Quaternion.identity);

        Vector3 rightPos = centerPos + Vector3.right * bounds.extents.x;
        Vector3 leftPos = centerPos + Vector3.left * bounds.extents.x;
        Vector3 upPos = centerPos + Vector3.up * bounds.extents.y;
        Vector3 downPos = centerPos + Vector3.down * bounds.extents.y;
        Vector3 forwardPos = centerPos + Vector3.forward * bounds.extents.z;
        Vector3 backPos = centerPos + Vector3.back * bounds.extents.z;

        rightPos = MoveHandle(rightPos);
        leftPos = MoveHandle(leftPos);
        upPos = MoveHandle(upPos);
        downPos = MoveHandle(downPos);
        forwardPos = MoveHandle(forwardPos);
        backPos = MoveHandle(backPos);

        if (EditorGUI.EndChangeCheck())
        {
            float xSize = rightPos.x - leftPos.x;
            float ySize = upPos.y - downPos.y;
            float zSize = forwardPos.z - backPos.z;

            if (xSize < 0)
            {
                leftPos.x += xSize;
                rightPos.x -= xSize;
            }

            if (ySize < 0)
            {
                downPos.y += ySize;
                upPos.y -= ySize;
            }

            if (zSize < 0)
            {
                backPos.z += zSize;
                forwardPos.z -= zSize;
            }

            bounds.size = new Vector3(Mathf.Abs(xSize), Mathf.Abs(ySize), Mathf.Abs(zSize));
            bounds.center = new Vector3((leftPos.x + rightPos.x) / 2, (upPos.y + downPos.y) / 2, (forwardPos.z + backPos.z) / 2);

            t.bounds = bounds;
            EditorUtility.SetDirty(t);
        }

        Handles.DrawWireCube(t.bounds.center, t.bounds.size);
    }

    Vector3 MoveHandle(Vector3 position)
    {
        float distance = Vector3.Distance(position, SceneView.currentDrawingSceneView.camera.transform.position);
        return Handles.FreeMoveHandle(position, Quaternion.identity, 0.01f * distance, Vector3.one * 0.5f, Handles.RectangleHandleCap);
    }
}

自分でコードを書くことなく簡単に思い通りの動きになりました。

ChatGPT

ChatGPTにはまず自分で作ったコードをそのまま送り、どんな処理かを答えてもらいました。

このスクリプトは、Unityエンジンで使用されるエディタ拡張の一部です。TestBoundsEditor というクラスは、Editor クラスを継承しており、特定のタイプのオブジェクト(この場合は TestBounds タイプのオブジェクト)のカスタムエディタインターフェイスを提供します。

ここでは TestBounds オブジェクトの境界ボックスを表示および操作するためのツールが提供されています。具体的には、シーンビューに6つのハンドルが表示され、それぞれがボックスの中心、右面、左面、上面、下面、表面、裏面を表しています。ユーザーはこれらのハンドルをドラッグしてボックスの形状を直接変更できます。

コードの主要部分は OnSceneGUI 関数です。ここでは各ハンドルが生成され、それらが移動された場合、境界ボックスの対応する次元が更新されます。境界ボックスの新しい形状は、最終的にワイヤーフレームで描画されます。

また、OnEnable と OnDisable 関数では、エディタのライフサイクルイベントに対して OnSceneGUI 関数の購読および購読解除を行っています。これにより、エディタがアクティブなときにのみシーンビューが更新され、必要なときにのみリソースが使用されるようになっています。

修正をお願いすると、何度か往復して完成コードを得ました。中央のハンドルと面のハンドルの両方に言及しないと、どちらかがおろそかになることもありました。

中央ハンドルが無い
面ハンドルが角にある

また、ハンドルの挙動に関する指示は間違って解釈されることもありました。

ある面を内側に動かして反対の面を通り過ぎたときに、サイズがマイナスになってしまいます。その場合反対の面もつられて一緒に動くようにできますか?
ある面を逆側に動かすと、実際には面がボックスを通過して反対側に移動してしまいます。そしてその面がボックスを通過したときに、実際にはボックスのサイズが負の値になり、結果的に反対の面が移動してしまいます。

この問題を修正するために、面がボックスを通過した際に、その面が反対側に移動するように修正を行うことができます。以下にその修正を加えたコードを示します:

-------

こちらの修正では、各面のハンドルが反対側に移動した際、その面がボックスを通過して反対側に移動するようにしています。

細かく指示するとうまく行きました。

コメントを残す

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