공부/인프런 - Rookiss

Part 7-2-4. Unity 2D : TileMap Collision

셩잇님 2024. 12. 13. 17:58
반응형

 

 

🎞 Unity 2D

 

 지난 시간에는 타일 맵 에디터를 이용하면서 레이어를 통해 base 영역과 Env 영역을 나누어 주는 작업을 진행하였다. 이렇게 레이어를 나누어주면 반투명한 물체를 그려주어도 base 영역의 레이어가 존재하기 때문에 자연스럽게 객체가 보여진다. 또한 이렇게 레이어를 나누게 될 경우 이번에 학습할 Collision과도 계산이 편리해지기 때문에 이를 나누어 사용한다. 따라서 이번 시간에는 Collision를 통해 갈 수 있는 영역과 갈 수 없는 영역을 구분하여 처리하는 로직에 대해서 알아보도록 하자.

 


 

💥 TileMap Collision

 

 먼저 지난 시간에 Tilemap_base를 그대로 복사-붙여넣기 하여 사용했더니 base의 잔디들을 그대로 가져와 사용해서 base 객체를 꺼도 잔디가 남아있는 문제가 있다. 따라서 만들어 주었던 Tilemap_env를 삭제하고, 새롭게 만들어주도록 하자. 만드는 방법은 이전 강의에서 다루었기 때문에 따로 작성하지 않는다. 이제 Collision을 추출해보도록 하자.

 

 새롭게 만들어준 Tilemap_env의 가서 Tilemap Collider 2D를 적용시켜보자. 

 

 

 하지만 콜라이더가 적용된 모습을 보면 우리가 원하던 네모 반듯한 모습이 아닌, 건물의 생김새 대로 콜라이더가 적용된 것을 볼 수 있다. 따라서 이렇게 적용하기가 싫다면, 빌딩 건물 객체를 클릭하여 콜라이더 타입을 변경하면 된다. 하지만 변경하더라도 우리가 원하는 모습이 나오지 않기 때문에, 다른 방법을 사용하도록 하자.

 

 

 이러한 문제를 해결하는 데에도 여러 방법이 있겠지만, 레이어를 새롭게 추가하는 형태로 진행하도록 하자. 따라서 Tilemap_Collision을 새롭게 만들어주자. 보편적인 상황이라면 'X' 이미지를 가진 이미지를 활용해 갈 수 없다라는 것을 표시하면 좋겠지만 현재를 그렇지 않으니 'rock'을 사용하여 처리하도록 하자.

 

rock 이미지를 활용해 갈 수 없는 장소를 표현한다.

 

Tilemap_Collision 레이어에 rock 이미지를 통해 이전에 배치해둔 집 등과 같이 갈 수 없는 장소를 돌로 다 막아버리는 작업을 하자. 따라서 base/env는 맵을 보여주는 용도, collision은 해당 장소를 갈 수 있느냐 없냐의 용도로 표현한다. 이제 이어서 해당 길을 서버에게도 알려줄 수 있도록 서버에게 공유하는 작업을 진행해보자.

 


 

서버 공유

 

서버와의 공유를 위해 새로운 스크립트를 하나 만들어주자. 그리고 Tilemap_Collision에 방금 만든 스크립트를 붙여 적용하자. 스크립트를 열어서 하고 싶은 것을 곰곰히 생각해보자. 우리가 해야 할 일은 결국 타일이 깔려있는 영역과, 그렇지 않은 영역을 구분하여 이를 별도의 파일로 저장해야 한다. 따라서 타일 하나하나의 정보가 필요한데, 이를 확인하기 위해 'Tilemap' 컴포넌트를 이용한다.

 

 

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

public class TestCollision : MonoBehaviour
{
    public Tilemap _tilemap;
    public TileBase _tile;

    void Start()
    {
    	// 0, 0, 0 위치에 타일을 깔아보자.
        _tilemap.SetTile(new Vector3Int(0, 0, 0), _tile);
    }
}

 

 Tilemap 클래스를 확인해보면 CellToLocal, CellTo~ 등 좌표를 셀 단위에서 로컬 또는 월드로 변환하는 여러 기능들이 있는 것을 볼 수 있다. 여기서는 SetTile이라는 함수를 통해 0, 0, 0에 _tile을 집어넣어 타일을 새로 만들어주는 것을 테스트해보자. 

 

0, 0, 0에 berrel이 하나 덜렁 생긴다

 

 따라서 이를 보면 동적으로 이를 생성하는 것도 가능하다는 것을 알 수 있다. 하지만 우리가 해결해야 하는 것은 모든 포지션을 스캔하여, 해당 포지션 위에 타일이 깔려 있는 것을 확인해야 한다.

 

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

public class TestCollision : MonoBehaviour
{
    public Tilemap _tilemap;
    public TileBase _tile;

	...

    void Update()
    {
        List<Vector3Int> blocked = new List<Vector3Int>();

        // 타일 맵의 모든 타일을 순회하며 타일이 있는 위치를 찾아내어 blocked 리스트에 추가
        foreach (Vector3Int pos in _tilemap.cellBounds.allPositionsWithin)
        {
            TileBase tile = _tilemap.GetTile(pos);
            if (tile != null)
            {
                blocked.Add(pos);
            }
        }
    }
}

 

 업데이트 문에서 foreach와 cellBoudns, allPositionWithin을 이용하여 타일 맵의 모든 타일을 순회하도록 하자. 이 후 포지션에 타일이 있을 경우 blocked 리스트에 이를 넣어주자. 

 

 

 사용자 맵 배치에 따라 값이 다르긴 하겠지만, 브레이크 포인트를 걸어 blocked 리스트를 확인해보면 모든 타일을 스캔하여 리스트 안에 값을 넣어준 것을 볼 수 있다. 다음으로는 유니티 확장을 통해 메뉴를 새롭게 만들고 해당 메뉴를 클릭할 경우 알아서 블록이 있는 값을 파악한뒤 파일로 추출해보는 것 까지 진행해보도록 하자.

 

 

반응형