내일배움캠프_TIL

10월 17일 TIL

skybluesky 2023. 10. 17. 22:39

팀프로젝트 랜덤맵 생성

 

미리 만들어둔 8x8 크기의 아이소메트릭 맵 프리팹을 전달받아서 지정된 가로,세로 크기만큼 방을 만들고 지정된 층 수만큼 반복해 건물 하나를 표현하는 맵을 생성한다

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

public class MapGenerator : MonoBehaviour
{
    public GameObject[] roomPrefabs; // 방 프리팹 배열

    private int[,] mapGrid; // 맵 그리드
    public int mapWidth; // 맵 가로 크기
    public int mapHeight; // 맵 세로 크기
    public int totalFloor;

    public List<GameObject> floors = new List<GameObject>();

    void Start()
    {
        mapGrid = new int[mapWidth, mapHeight];
        GenerateFloors(totalFloor);
        ActivateFloor(0);
    }

    void GenerateFloors(int floorCount)
    {
        for (int i = 0; i < floorCount; i++)
        {
            mapGrid = new int[mapWidth, mapHeight];
            GenerateMap();
            InstantiateRooms();
        }
    }

    void GenerateMap()
    {
        for (int x = 0; x < mapWidth; x++)
        {
            for (int y = 0; y < mapHeight; y++)
            {
                if (x == 0 || y == 0 || x == mapWidth - 1 || y == mapHeight - 1)
                {
                    // 경계는 벽으로 처리
                    mapGrid[x, y] = -1;
                }
                else
                {
                    // 내부는 랜덤하게 방 배치
                    int roomIndex = Random.Range(0, roomPrefabs.Length);
                    mapGrid[x, y] = roomIndex;
                }
            }
        }
    }

    void InstantiateRooms()
    {
        GameObject floor = new GameObject("Floor");
        floor.transform.position = Vector3.zero;
        floors.Add(floor);

        for (int x = 0; x < mapWidth; x++)
        {
            for (int y = 0; y < mapHeight; y++)
            {
                if (mapGrid[x, y] != -1)
                {
                    Vector3 positionIsoMetric = new Vector3((x - y) * 4f, (-x - y) * 2f, y - x);
                    GameObject roomInstance = Instantiate(roomPrefabs[mapGrid[x, y]], positionIsoMetric, Quaternion.identity);
                    roomInstance.transform.parent = floor.transform;
                    UpdateSortingOrder(roomInstance);
                }
            }
        }

        floor.SetActive(false);
    }

    void ActivateFloor(int index)
    {
        for (int i = 0; i < floors.Count; i++)
        {
            if (i == index) floors[i].SetActive(true);
            else floors[i].SetActive(false);
        }
    }

    void UpdateSortingOrder(GameObject instance)
    {
        // 인스턴스 자체에 대한 Renderer 컴포넌트 찾기
        Renderer renderer = instance.GetComponent<Renderer>();

        if (renderer != null)
        {
            // 기존 sortingOrder와 Y 위치를 고려하여 새로운 sortingOrder 설정
            renderer.sortingOrder += -Mathf.RoundToInt(instance.transform.position.y * 100);
        }

        // 인스턴스의 자식들에 대한 모든 Renderer 컴포넌트 찾기
        Renderer[] childRenderers = instance.GetComponentsInChildren<Renderer>();

        foreach (Renderer childRenderer in childRenderers)
        {
            if (childRenderer != renderer)  // 부모 오브젝트를 제외하기 위한 체크
            {
                // 기존 sortingOrder와 Y 위치 및 깊이(depth)를 고려하여 새로운 sortingOrder 설정. 여기서 '10'은 임의로 선택한 값으로, 실제 프로젝트에서는 필요에 따라 조정해야 합니다.
                childRenderer.sortingOrder += -Mathf.RoundToInt(childRenderer.transform.position.y * 100 + childRenderer.transform.position.z * 10);
            }
        }
    }
}
    void GenerateMap()
    {
        for (int x = 0; x < mapWidth; x++)
        {
            for (int y = 0; y < mapHeight; y++)
            {
                if (x == 0 || y == 0 || x == mapWidth - 1 || y == mapHeight - 1)
                {
                    // 경계는 벽으로 처리
                    mapGrid[x, y] = -1;
                }
                else
                {
                    // 내부는 랜덤하게 방 배치
                    int roomIndex = Random.Range(0, roomPrefabs.Length);
                    mapGrid[x, y] = roomIndex;
                }
            }
        }
    }
        void InstantiateRooms()
    {
        GameObject floor = new GameObject("Floor");
        floor.transform.position = Vector3.zero;
        floors.Add(floor);

        for (int x = 0; x < mapWidth; x++)
        {
            for (int y = 0; y < mapHeight; y++)
            {
                if (mapGrid[x, y] != -1)
                {
                    Vector3 positionIsoMetric = new Vector3((x - y) * 4f, (-x - y) * 2f, y - x);
                    GameObject roomInstance = Instantiate(roomPrefabs[mapGrid[x, y]], positionIsoMetric, Quaternion.identity);
                    roomInstance.transform.parent = floor.transform;
                    UpdateSortingOrder(roomInstance);
                }
            }
        }

        floor.SetActive(false);
    }

1개의 층을 만드는 메서드

    void GenerateFloors(int floorCount)
    {
        for (int i = 0; i < floorCount; i++)
        {
            mapGrid = new int[mapWidth, mapHeight];
            GenerateMap();
            InstantiateRooms();
        }
    }

입력받은 층 수만큼 맵을 반복해서 생성

    void ActivateFloor(int index)
    {
        for (int i = 0; i < floors.Count; i++)
        {
            if (i == index) floors[i].SetActive(true);
            else floors[i].SetActive(false);
        }
    }

현재 플레이어가 위치한 층을 제외한 맵들을 비활성화
계단과 상호작용하면 활성화된 층이 변경되도록 구현 예정

    void UpdateSortingOrder(GameObject instance)
    {
        // 인스턴스 자체에 대한 Renderer 컴포넌트 찾기
        Renderer renderer = instance.GetComponent<Renderer>();

        if (renderer != null)
        {
            // 기존 sortingOrder와 Y 위치를 고려하여 새로운 sortingOrder 설정
            renderer.sortingOrder += -Mathf.RoundToInt(instance.transform.position.y * 100);
        }

        // 인스턴스의 자식들에 대한 모든 Renderer 컴포넌트 찾기
        Renderer[] childRenderers = instance.GetComponentsInChildren<Renderer>();

        foreach (Renderer childRenderer in childRenderers)
        {
            if (childRenderer != renderer)  // 부모 오브젝트를 제외하기 위한 체크
            {
                // 기존 sortingOrder와 Y 위치 및 깊이(depth)를 고려하여 새로운 sortingOrder 설정. 여기서 '10'은 임의로 선택한 값으로, 실제 프로젝트에서는 필요에 따라 조정해야 합니다.
                childRenderer.sortingOrder += -Mathf.RoundToInt(childRenderer.transform.position.y * 100 + childRenderer.transform.position.z * 10);
            }
        }
    }

생성된 맵들의 렌더러 정렬