본문 바로가기
공부

랜덤 맵 생성] 2. 횡스크롤 수평 랜덤맵 타일맵으로 만들기

by 때려쳐아니때려치지마 2025. 2. 19.

 

https://workdiarysometimesnot.tistory.com/126

 

랜덤 맵 생성] 1. 횡스크롤 수평 랜덤맵 생성하기

구현 목표 리스트1920 * 1080을 기준으로 16 : 9 비율의 화면에서 수평적인 랜덤 맵을 생성한다.수평칸 내에서 생성되는 방은 (맵 내의 분리된 개별 공간을 ‘방’이라고 명명) 서로 떨어져 있다.수

workdiarysometimesnot.tistory.com

이전 포스팅에서 디버그 및 오브젝트로 맵을 시각화 하였다.

1920*1080 사이즈의 월드에서 ground를 오브젝트로 인스턴스 하였는데

씬뷰가 1920 * 1080이라면 실제 월드는 그보다 더 큰 사이즈 일것이다.

또한 땅만 있는것이 아니라 tilemap을 사용하여 땅, 벽, 천장, 배경이 있는 방을 구현하고자 한다.

 

구현목록

  • 맵 사이즈를 변동적으로 바꿀수 있게 설정
  • 타일맵으로 맵 구현하기

1. 맵사이즈 변동적으로 적용하기

private void SetWorldArea()
{
    _gridSizePixelX = _mapSizePixel.x / _gridColums;
    _gridSizePixelY = _mapSizePixel.y / _gridLows;

    // 한 칸의 좌표 구하기
    _mapBottomLeft = _cam.ViewportToWorldPoint(new Vector3(0, 0, Mathf.Abs(_cam.transform.position.z))); // 좌측하단
    _mapTopRight = _cam.ViewportToWorldPoint(new Vector3(1, 1, Mathf.Abs(_cam.transform.position.z))); // 우측상단
    _mapBottomLeft.z = 0;
    _mapTopRight.z = 0;

    // 한 칸의 사이즈 구하기
    float cellWidth = Mathf.Abs(_mapTopRight.x - _mapBottomLeft.x);
    float cellHeight = Mathf.Abs(_mapTopRight.y - _mapBottomLeft.y);

    // 월드의 전체 영역 사이즈 구하기
    float worldWidth = cellWidth * _gridColums;
    float worldHeight = cellHeight * _gridLows;

    // 홀수는 가운데, 짝수는 절반 값 위치로 중앙 설정하여 top 계산
    float yOffset = (_gridLows % 2 == 0) ? (cellHeight * 0.5f) : 0;
    float worldTopLeftY = _mapTopRight.y + (Mathf.FloorToInt(_gridLows / 2) * (cellHeight + yOffset));

    // 월드 전체 영역의 가운데 좌표
    Vector3 worldCenter = new Vector3(
        _mapBottomLeft.x + (worldWidth * 0.5f),
        worldTopLeftY - (worldHeight * 0.5f),
        0);

    // 월드의 좌측하단, 우측상단 재설정
    _mapBottomLeft = worldCenter - new Vector3(worldWidth, worldHeight, 0) * 0.5f;
    _mapTopRight = worldCenter + new Vector3(worldWidth, worldHeight, 0) * 0.5f;

    _mapSizeWorldMin = new Vector2(cellWidth, cellHeight);
}

mapSize : 맵사이즈 크기를 입력 (pixel)

gridColums, gridLows : 맵을 분할할 행열 개

 

적용하면 이렇게 큰 사이즈의 맵을 그리드로 분할할수있다.

빨간 라인으로 나눠진 한칸의 사이즈가 scene의 screen 사이즈다.


2. 타일맵으로 맵 구현하기

미리 찍는 타일맵이 아니라 랜덤방을 런타임중에 생성하려고함

// set tilemap
    private void TilingMap()
    {
        Vector2 oneTileSize = new Vector2(_mapSizeWorldMin.x / GRID_WIDTH, _mapSizeWorldMin.y / GRID_HEIGHT);
        foreach (var level in levels)
        {
            foreach (var node in level.Value)
            {
                GameObject mapInstanced = Instantiate(_groundOBJ.gameObject);
                SimpleGround ground = mapInstanced.GetComponent<SimpleGround>();

                if (ground == null)
                {
                    return;
                }

                // background
                float x = _mapBottomLeft.x + (node.x * _mapSizeWorldMin.x);
                float y = _mapBottomLeft.y + (node.y * _mapSizeWorldMin.y);
                _tileMapController.SetTileArea(MapTile.Background, new Vector3(x, y, _mapBottomLeft.z), node.length * GRID_WIDTH, GRID_HEIGHT);

                // wall 
                _tileMapController.SetTileArea(MapTile.WallLeft, new Vector3(x, y, _mapBottomLeft.z), 1, GRID_HEIGHT);
                x += node.length * _mapSizeWorldMin.x - oneTileSize.x;
                _tileMapController.SetTileArea(MapTile.WallRight, new Vector3(x, y, _mapBottomLeft.z), 1, GRID_HEIGHT);

                // ceiling
                x = _mapBottomLeft.x + (node.x * _mapSizeWorldMin.x);
                y += _mapSizeWorldMin.y - oneTileSize.y;
                _tileMapController.SetTileArea(MapTile.Ceiling, new Vector3(x, y, _mapBottomLeft.z), node.length * GRID_WIDTH, 1);

                // ground
                x = _mapBottomLeft.x + (node.x * _mapSizeWorldMin.x);
                y = _mapBottomLeft.y + (node.y * _mapSizeWorldMin.y);
                _tileMapController.SetTileArea(MapTile.Ground, new Vector3(x, y, _mapBottomLeft.z), node.length * GRID_WIDTH, 1);
            }
        }
    }

grid가 맞춰진 이후 바닥, 벽, 천장, 배경을 나눠 tile을 만들어주었다

 

구현된 모습


타일맵이 유니티의 기본 grid를 기준으로 생성되기 때문에 내 카메라 설정의 screen영역과 정확하게 grid가 일치하지 않는 경우가 생겼다.

따로 해당 이슈를 해결한 트러블슈팅 정리 문서를 첨부한다.

댓글