コガネブログ

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

【Unity】Tilemap のすべてのタイルをカーソルキーで上下左右にずらすことができるエディタ拡張

ソースコード

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 currentEvent   = Event.current;
        var modifiers      = currentEvent.modifiers;
        var isKey          = currentEvent.isKey;
        var isKeyDown      = currentEvent.type == EventType.KeyDown;
        var isFunctionKey  = modifiers == EventModifiers.None || modifiers == EventModifiers.FunctionKey;
        var isOrthographic = sceneView.camera.orthographic;

        if ( !isKey || !isKeyDown || !isFunctionKey || !isOrthographic ) return;

        switch ( currentEvent.keyCode )
        {
            case KeyCode.RightArrow:
                Shift( Vector2Int.right );
                break;
            case KeyCode.LeftArrow:
                Shift( Vector2Int.left );
                break;
            case KeyCode.UpArrow:
                Shift( Vector2Int.up );
                break;
            case KeyCode.DownArrow:
                Shift( Vector2Int.down );
                break;
        }

        currentEvent.Use();
    }

    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:20191014201843g:plain