げんとめブログ

UnityのTilemapをプレイモード中に編集する

実行中に編集したいTilemapが一つだけなら以下の方法でもできます。

  1. プレイモード中にタイルマップを編集する。
  2. プレイモード終了前に目的のTilemapコンポーネントをインスペクタから右クリックして「Copy Component」する。
  3. プレイモード終了後、コピーしたコンポーネントを元のTilemapオブジェクトに「Paste Component」すればプレイモード中に編集した内容を残せる。

ただ複数のTilemapを編集出来ないし、ちょっと面倒ではある。それにコライダーを一回OnOffしないと反映されてないっぽい気もする。

Editor拡張で何とかする。

プレイモード終了時にタイルマップのデータをキャッシュしてエディタに戻る時にキャッシュしたデータをセットする。

Editorフォルダを作ってその中に以下のスクリプトをコピーする。

Editorフォルダ以下でないとビルドしたときにエラーが出る。

[Window]から開けます。

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

public class TilemapPersistent:EditorWindow
{
    [SerializeField]
    private Tilemap[] target;
    List<TileBase[]> cachedAllTiles = new List<TileBase[]>();
    List<BoundsInt> cachedBounds = new List<BoundsInt>();
    [MenuItem("Window/TilemapExtend")]
    static void ShowWindow()
    {
        EditorWindow.GetWindow<TilemapPersistent>();
    }

    private void OnGUI()
    {
        SetArrayProp();
        EditorGUILayout.LabelField("プレイモード中に編集したタイルマップをそのままにします");
        EditorGUILayout.LabelField("このウィンドウを開いていないと変更されません");
    }

    private void SetArrayProp()
    {
        ScriptableObject target = this;
        SerializedObject so = new SerializedObject(target);
        SerializedProperty tilemaps = so.FindProperty("target");
        EditorGUILayout.PropertyField(tilemaps, true);
        so.ApplyModifiedProperties();
    }

    /// <summary>
    /// エディタの状態が変更されたときのコールバックをセットする
    /// </summary>
    private void OnEnable()
    {
        EditorApplication.playModeStateChanged += OnChangePlayMode;
    }

    private void OnDisable()
    {
        EditorApplication.playModeStateChanged -= OnChangePlayMode;
    }
    private void OnChangePlayMode(PlayModeStateChange playmode)
    {
        switch (playmode)
        {
            //プレイモードが終わって
            case PlayModeStateChange.EnteredEditMode:
                for (var i = 0; i < cachedBounds.Count; i++)
                {
                    target[i].SetTilesBlock(cachedBounds[i],cachedAllTiles[i]);
                }
                break;
            //プレイモード終了時
            case PlayModeStateChange.ExitingPlayMode:
                cachedAllTiles.Clear();
                cachedBounds.Clear();
                foreach (var tilemap in target)
                {
                    //タイルデータの取得
                    BoundsInt bounds = tilemap.cellBounds;//タイルの範囲を取得
                    TileBase[] allTiles = tilemap.GetTilesBlock(bounds);//範囲内のタイルを取得
                    cachedBounds.Add(bounds);
                    cachedAllTiles.Add(allTiles);
                }
                break;
        }
    }
}

タイルデータの取得方法を探すのに苦戦した。

Exit mobile version