コガネブログ

平日更新を目標に Unity や C#、Visual Studio、ReSharper などのゲーム開発アレコレを書いていきます

【Unity】Tilemap のすべてのタイルを上下左右にずらすボタンを Scene ビューに表示するエディタ拡張

ソースコード

using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.Tilemaps;

[InitializeOnLoad]
internal static class TilemapShifter
{
    private class TileInfo
    {
        public readonly Vector3Int m_position;
        public readonly TileBase   m_tile;

        public TileInfo( Vector3Int position, TileBase tile )
        {
            m_position = position;
            m_tile     = tile;
        }
    }

    static TilemapShifter()
    {
        SceneView.onSceneGUIDelegate -= OnGUI;
        SceneView.onSceneGUIDelegate += OnGUI;
    }

    private static void OnGUI( SceneView sceneView )
    {
        var screenRect = new Rect( 8, 24, 80, 0 );
        
        GUI.WindowFunction func = id =>
        {
            using ( new EditorGUILayout.HorizontalScope() )
            {
                if ( GUILayout.Button( "↑" ) )
                {
                    Shift( Vector2Int.up );
                }
            }

            using ( new EditorGUILayout.HorizontalScope() )
            {
                if ( GUILayout.Button( "←" ) )
                {
                    Shift( Vector2Int.left );
                }

                if ( GUILayout.Button( "→" ) )
                {
                    Shift( Vector2Int.right );
                }
            }

            using ( new EditorGUILayout.HorizontalScope() )
            {
                if ( GUILayout.Button( "↓" ) )
                {
                    Shift( Vector2Int.down );
                }
            }
        };
        
        Handles.BeginGUI();
        GUILayout.Window( 12345, screenRect, func, "Tilemap" );
        Handles.EndGUI();
    }

    private static void Shift( Vector2Int offset )
    {
        var tilemap = GameObject.FindObjectOfType<Tilemap>();
        var bound   = tilemap.cellBounds;

        var list = new List<TileInfo>();

        for ( int y = bound.max.y - 1; y >= bound.min.y; --y )
        {
            for ( int x = bound.min.x; x < bound.max.x; ++x )
            {
                var position = new Vector3Int( x, y, 0 );
                var tile     = tilemap.GetTile( position );
                var info     = new TileInfo( position, tile );

                list.Add( info );
            }
        }

        if ( list.Count <= 0 ) return;

        Undo.RecordObject( tilemap, "Shift Tilemap" );

        tilemap.ClearAllTiles();

        foreach ( var data in list )
        {
            var position = data.m_position;
            position.x += offset.x;
            position.y += offset.y;
            tilemap.SetTile( position, data.m_tile );
        }

        tilemap.RefreshAllTiles();
    }
}

f:id:baba_s:20191014200634p:plain

注意

  • ボタンが押せなくなることがあるので要検証