Привет можешь немного изменить скрипт для юнити 3д. ОН создает бесконечный мир используя шум пятна и в зависимости от высоты разные префабы. Можешь сделать чтобы было всего 3 уровня и чтобы для каждого уровня можно было выбрать собственный префаб который повернут на случайную сторону

using UnityEngine;
using System.Collections.Generic;

public class InfiniteWorld : MonoBehaviour
{
    public GameObject[] chunkPrefabs; // Префабы для разных цветов
    public Transform playerTransform;
    public int chunkSize = 100;
    public int renderDistance = 4;

    private Dictionary<Vector2, GameObject> activeChunks = new Dictionary<Vector2, GameObject>();
    private Vector2 lastPlayerChunkPos;
    public float noiseScale = 0.1f; // Масштаб шума Перлина
    public float noiseOffset = 1000f; // Смещение, чтобы шум выглядел более хаотично

    void Start()
    {
        lastPlayerChunkPos = GetChunkPosition(playerTransform.position);
        UpdateChunks();
    }

    void Update()
    {
        Vector2 currentChunkPos = GetChunkPosition(playerTransform.position);
        if (!currentChunkPos.Equals(lastPlayerChunkPos))
        {
            lastPlayerChunkPos = currentChunkPos;
            UpdateChunks();
        }
    }

    Vector2 GetChunkPosition(Vector3 position)
    {
        return new Vector2(
            Mathf.FloorToInt(position.x / chunkSize),
            Mathf.FloorToInt(position.z / chunkSize)
        );
    }

    void UpdateChunks()
    {
        Vector2 playerChunkPos = GetChunkPosition(playerTransform.position);

        // Удаление старых чанков
        var chunksToRemove = new List<Vector2>();
        foreach (var pos in activeChunks.Keys)
        {
            if (Vector2.Distance(playerChunkPos, pos) > renderDistance)
            {
                chunksToRemove.Add(pos);
            }
        }

        foreach (var pos in chunksToRemove)
        {
            Destroy(activeChunks[pos]);
            activeChunks.Remove(pos);
        }

        // Создание новых чанков в круглой области
        for (int x = -renderDistance; x <= renderDistance; x++)
        {
            for (int z = -renderDistance; z <= renderDistance; z++)
            {
                Vector2 newChunkPos = playerChunkPos + new Vector2(x, z);
                if (!activeChunks.ContainsKey(newChunkPos) && Vector2.Distance(playerChunkPos, newChunkPos) <= renderDistance)
                {
                    float noiseValue = GetPerlinNoise(newChunkPos);

                    GameObject newChunkPrefab = SelectPrefabBasedOnNoise(noiseValue);
                    GameObject newChunk = Instantiate(newChunkPrefab,
                        new Vector3(newChunkPos.x * chunkSize, 0, newChunkPos.y * chunkSize),
                        Quaternion.identity
                    );
                    activeChunks[newChunkPos] = newChunk;
                }
            }
        }
    }

    float GetPerlinNoise(Vector2 chunkPos)
    {
        float noise1 = Mathf.PerlinNoise((chunkPos.x + 0.1f) * noiseScale, (chunkPos.y + 0.1f) * noiseScale);
        float noise2 = Mathf.PerlinNoise((chunkPos.x + 0.1f + noiseOffset) * noiseScale, (chunkPos.y + 0.1f + noiseOffset) * noiseScale);
        return (noise1 + noise2) / 2f; // Усреднение двух шумовых значений
    }

    GameObject SelectPrefabBasedOnNoise(float noiseValue)
    {
        if (noiseValue < 0.3f)
        {
            return chunkPrefabs[0]; // 1
        }
        else if (noiseValue < 0.5f)
        {
            return chunkPrefabs[1]; // 2
        }
        else if (noiseValue < 0.6f)
        {
            return chunkPrefabs[2]; // 3
        }
        else if (noiseValue < 0.7f)
        {
            return chunkPrefabs[3]; // 4
        }
        else if (noiseValue < 0.8f)
        {
            return chunkPrefabs[4]; // 5
        }
        else
        {
            return chunkPrefabs[5]; // 6
        }
    }
}