Unity2Dのタイルマップ(Tilemap)でランダムなマップをPerlinNoiseを利用して作成してみます。
はじめに
Unityのバージョンは6000.5.2f1です。下記記事にてランダムなマップを生成してました。
記事内で作成したスクリプトは下記となっており、ランダムでタイルを選択しています。
using UnityEngine;
using UnityEngine.Tilemaps;
public class MapGenerate : MonoBehaviour
{
[SerializeField] private Tilemap tilemap;
[SerializeField] private int mapSize;
[SerializeField] private Tile[] tiles;
private void Start()
{
RandomMapGenerate();
}
private void RandomMapGenerate()
{
for (int y = 0; y < mapSize; y++)
{
for (int x = 0; x < mapSize; x++)
{
Tile tile = tiles[Random.Range(0, tiles.Length)];
tilemap.SetTile(new Vector3Int(x - mapSize / 2, y - mapSize / 2, 0), tile);
}
}
}
}
実行すると下記の様な形になります。

個々のタイルをランダムでセットしており、実際のマップとして考えた場合不自然な形なので、今回は自然な形に近いマップを「PerlinNoise」を利用して作成します。
作成開始
マップ生成のスクリプトを下記に変更します。高さをPerlinNoiseで生成、高さに応じてタイルをセットしています。
using UnityEngine;
using UnityEngine.Tilemaps;
[System.Serializable]
public struct TileData
{
public Tile tile;
public float minHeight;
public float maxHeight;
}
public class MapGenerate : MonoBehaviour
{
[SerializeField] private Tilemap tilemap;
[SerializeField] private int mapSize;
[SerializeField] private TileData[] tileDatas;
private float scale = 5f;
private void Start()
{
RandomMapGenerate();
}
private void RandomMapGenerate()
{
for (int y = 0; y < mapSize; y++)
{
for (int x = 0; x < mapSize; x++)
{
float xCoord = (float)x / mapSize * scale;
float yCoord = (float)y / mapSize * scale;
float height = Mathf.PerlinNoise(xCoord, yCoord);
foreach (TileData tileData in tileDatas)
{
if (height >= tileData.minHeight && height <= tileData.maxHeight)
{
tilemap.SetTile(new Vector3Int
(x - mapSize / 2, y - mapSize / 2, 0), tileData.tile);
break;
}
}
}
}
}
}
パラメータをセットします。Height(高さ)は0~1で割り当てます。

「PerlinNoise」を利用するとランダム値が波で作成されるのでアニメーション、地形などに利用できます。下記が公式リファレンスです。
実行すると下記の様な感じに。地形感がでます。

下記の様にランダム値を追加することで、実行するごとに違うマップを生成することが出来ます。
private void RandomMapGenerate()
{
float random = Random.Range(0f, 100f);
for (int y = 0; y < mapSize; y++)
{
for (int x = 0; x < mapSize; x++)
{
float xCoord = ((float)x+random) / mapSize * scale;
float yCoord = ((float)y+random) / mapSize * scale;
float height = Mathf.PerlinNoise(xCoord, yCoord);
foreach (TileData tileData in tileDatas)
{
if (height >= tileData.minHeight && height <= tileData.maxHeight)
{
tilemap.SetTile(new Vector3Int
(x - mapSize / 2, y - mapSize / 2, 0), tileData.tile);
break;
}
}
}
}
}


