Victo-Epeso’s diary

元RiotTheSplitter[TheSequel夕暮れにさよなら] THE 科学究極 個人徹萼 [CherinosBorges Tell‘A‘Bout] ノーベルノークスクラム賞狙い 右上Profileより特記事項アリ〼 何かあったらコメント欄よりお便り待ってマス

📦 UnityでTilemapから3Dマップ作成

Unityで2Dのマップを作成するために使うTilemap機能。

これを利用してシンプルな3Dマップくらいなら
簡単に生成できるんじゃないかと思い専用のエディターを作成した。


手順(1)
新しいSceneを作りTilemapと変換用のScriptを作成。


手順(2)
変換用Scriptのコードを書いていく。

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

//Inspectorで編集しやすくするためclassを追加
[System.Serializable]
class ConvertTile
{
    [SerializeField]
    TileBase tile = null;

    [SerializeField]
    GameObject prefab = null;

    public TileBase GetTile()
    {
        return tile;
    }
    public GameObject GetPrefab()
    {
        return prefab;
    }
}

public class MapConverterEX : MonoBehaviour
{
    //変換元のTilemap
    [SerializeField]
    private Tilemap setTileMap;

    //Tileの変換対応List
    [SerializeField]
    private List<ConvertTile> convertTiles = new List<ConvertTile>();

    //変換後Object1マスあたりのサイズ
    [SerializeField]
    private float nodeSizeX;
    [SerializeField]
    private float nodeSizeY;

    //Inspectorのボタンから呼び出し
    public void ConvertMapTile()
    {
        //タイルマップのサイズ
        int sizeX = setTileMap.size.x;
        int sizeY = setTileMap.size.y;
        //タイル座標がマイナスの値を取りうるのでとりあえず検索範囲を倍にして対応(要修正点)
        int scanX = sizeX * 2;
        int scanY = sizeY * 2;

        //新しいGameObjectのルート
        GameObject newParent = new GameObject("NewMap");
        Undo.RegisterCreatedObjectUndo(newParent"Create New GameObject");

        //Tilemapを検索してObject生成
        for (int cy = 0cy < scanYcy++)
        {
            for (int cx = 0cx < scanXcx++)
            {
                Vector3Int cellPosition = new Vector3Int( cx - sizeX,cy - sizeY,0 );
                TileBase getTile = setTileMap.GetTile( cellPosition );
                
                if ( getTile != null )
                {
                    var target = FindTile( getTile );
                    if ( ( target != null ) && ( target.GetPrefab() != null ) )
                    {
                        GameObject newGameObject = ( GameObject ) Instantiate( target.GetPrefab() );
                        newGameObject.transform.position = new Vector3( ( cx - sizeX ) * nodeSizeX0.0f, ( cy - sizeY ) * nodeSizeY );
                        newGameObject.transform.parent = newParent.transform;
                        Undo.RegisterCreatedObjectUndo( newGameObject"Create New GameObject" );
                    }
                }
            }
        }
    }

    //変換対応Listを検索
    ConvertTile FindTile(TileBase searchTile)
    {
        return convertTiles.Find(tile => tile.GetTile() == searchTile);
    }
}


手順(3)
Inspectorを拡張するためEditorフォルダにScriptを追加。

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

[CustomEditor(typeof(MapConverterEX))]
public class MapConverterEXEditor : Editor
{
    private MapConverterEX _target;
    private void OnEnable()
    {
            _target = (MapConverterEX)target;
    }

    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();

        if (GUILayout.Button("タイルマップ -> マップ変換"))
        {
            _target.ConvertMapTile();
        }
    }
}


手順(4)
ひとまず完成、使ってみる

作成。緑のタイルに壁を割り当て、紫はnull。

全体図はこんな感じ。

製作中の自作ゲーム用に作ったモノで、まだ色々と粗はあるが、
とりあえず昔ながらのシンプルな3DダンジョンRPGのマップくらいは作れるはず。