Prefabをタイルマップのように簡単に配置する

Unityエディターのバージョン:2022.3.16f1

タイルマップはタイルごとに取得して処理を行うのが難しいのでPrefabを並べることにしました
どうすればタイルマップみたいにマウスで絵を描くように配置できるか悩んでいたところ、エディタ拡張について耳にしたのでChatGPTに聞いてみました
最初はうまくいかなかったのですが「座標を整数+0.5にして」とかプロンプトを工夫したら便利なツールを作ってくれました

using UnityEngine;
using UnityEditor;

public class PrefabBrush : EditorWindow
{
    private GameObject prefab; // 配置するPrefab
    private GameObject parentObject; // 親オブジェクト
    private Vector3 placementPosition; // 配置予定の位置
    private Vector3 lastPlacedPosition; // 最後に配置した位置
    private bool isPlacing = false; // プレハブを配置中かどうか

    [MenuItem("Tools/Prefab Brush")] // メニューに追加
    public static void ShowWindow()
    {
        GetWindow<PrefabBrush>("Prefab Brush");
    }

    private void OnEnable()
    {
        SceneView.duringSceneGui += OnSceneGUI; // シーンビューで描画するように登録
    }

    private void OnDisable()
    {
        SceneView.duringSceneGui -= OnSceneGUI; // シーンビューから削除
    }

    private void OnGUI()
    {
        GUILayout.Label("Prefab Brush", EditorStyles.boldLabel);
        prefab = (GameObject)EditorGUILayout.ObjectField("Prefab", prefab, typeof(GameObject), false);
        parentObject = (GameObject)EditorGUILayout.ObjectField("Parent Object", parentObject, typeof(GameObject), true); // 親オブジェクトのフィールドを追加
    }

    private void OnSceneGUI(SceneView sceneView)
    {
        Event e = Event.current;

        // マウス座標をワールド座標に変換
        Ray ray = HandleUtility.GUIPointToWorldRay(e.mousePosition);
        RaycastHit hit;

        // シーンビュー内で平面との交点を取得
        if (Physics.Raycast(ray, out hit))
        {
            // 配置位置を整数+0.5にスナップ
            float snapX = Mathf.Floor(hit.point.x) + 0.5f;
            float snapY = Mathf.Floor(hit.point.y) + 0.5f;  // y座標も整数+0.5にスナップ
            float snapZ = Mathf.Floor(hit.point.z) + 0.5f;

            // スナップされた位置を設定
            placementPosition = new Vector3(snapX, snapY, snapZ);
        }
        else
        {
            placementPosition = ray.origin + ray.direction * 10f;  // ヒットしなかった場合の代替座標(適当な位置)
        }

        // 整数+0.5の位置にスナップ
        placementPosition.x = Mathf.Floor(placementPosition.x) + 0.5f;
        placementPosition.y = Mathf.Floor(placementPosition.y) + 0.5f;
        placementPosition.z = Mathf.Floor(placementPosition.z) + 0.5f;

        // ガイドを描画(緑色のワイヤーキューブ)
        Handles.color = Color.green;
        Handles.DrawWireCube(placementPosition, Vector3.one); // サイズ1のワイヤーフレームで描画

        // クリックしてPrefabを配置
        if (e.type == EventType.MouseDown && e.button == 0 && prefab != null)
        {
            lastPlacedPosition = placementPosition;  // 最初に配置した位置を記録
            PlacePrefab();
            isPlacing = true; // 配置を開始
            e.Use(); // イベントを消費
        }
        else if (e.type == EventType.MouseDrag && e.button == 0 && prefab != null && isPlacing)
        {
            // 位置が前回と違う場合にのみPrefabを配置
            if (placementPosition != lastPlacedPosition)
            {
                lastPlacedPosition = placementPosition;
                PlacePrefab();
            }
        }
        else if (e.type == EventType.MouseUp && e.button == 0)
        {
            isPlacing = false; // 長押し終了
        }

        SceneView.RepaintAll(); // シーンビューを更新
    }

    private void PlacePrefab()
    {
        // Prefabを配置
        GameObject newObject = (GameObject)PrefabUtility.InstantiatePrefab(prefab);
        newObject.transform.position = placementPosition;

        // 親オブジェクトが指定されていれば、親オブジェクトの子として設定
        if (parentObject != null)
        {
            newObject.transform.SetParent(parentObject.transform);
        }

        // Undoに登録して元に戻せるようにする
        Undo.RegisterCreatedObjectUndo(newObject, "Place Prefab");
    }
}

親オブジェクトを指定することもできるので親オブジェクトにComposite Collider 2DとPlatform Effector 2Dをアタッチすれば下からすり抜ける足場の縦スクロールアクションが作れます
しかしこのツールはPrefabを削除する消しゴム機能が無いなどまだ不便なところがあり毎回AIに頼るわけにもいかないので、そろそろエディタ拡張も勉強しなきゃいけないです