[내일배움캠프 4주차] Isomatric의 트러블슈팅

하얀요니콘·2025년 7월 24일

우선 해당 주차의 내용을 Tilemap에 활용하며, 2D환경에 맵을 구현하는 상황이 되었다.
이제 Unity Asset Store에서 무료 타일맵들을 보다가 마음에 드는 에셋이 있어 사용을 하였다. 하지만 모든 문제는 이 타일들에서 시작되었다.

Isomatric Tilemap

이 에셋은 2.5D를 표현하는 Isomatric 좌표계를 사용해야한다. Isomatric은 대각선으로 구성된 타일맵으로, 이제 대각선처럼 보이는 Isomatric을 작업하기 위해서 몇가지 트러블이 있었다.

1. Isomatric의 그리드 각도

우선 타일들의 사이즈를 확인 할 필요가 생겼다. 왜냐하면 타일들을 TilePalette에 넣어보니, 각도의 Allign 이 맞지 않아 타일 배치시 겹치는 문제가 발생하였다.

우선 이를 해결하기 위해서는 에셋의 가로 : 세로 비율을 알 필요가 있다. 우선 그 전에 에셋의 비율에 맞춰 Pixel Per Unit부터 맞춰주자. 그래야 그리드 사이즈가 맞는다. 자 그럼 그리드를 맞췄으니, 그리드를 맞춰보자.

그리드 생성시 x,y,z는 비율에 맞춰야 한다. 이제 아까 보았던 이미지의 비율을 가지고 작업을 해 주는데, PixelPerUnit과 높이를 고려하여 x는 Unit 수, y를 (세로) / (가로) * 2 정도의 값으로 설정해주는 얼추 그리드가 맞는 느낌이 들어서 이렇게 작업 해 주었다.

2. Isomatric의 tilemap 겹침현상

자 이제 타일을 다 만들었으니 깔려고 보았는데, 몇몇 타일들이 높이 정렬이 되지 않고, 앞에 가야할게 뒤에있는 그런 현상들이 몇가지 발생하였다. 아직 완전히 해결은 못한것 같지만 일부 해결방법이 정리되어 작성한다.

  1. Isomatric이 아닌 Isomatric Z as Y를 사용해준다. 이는 캔버스의 Z값을 레이어 순서처럼 사용 할 수 있게 해 주는 작업이다.
  2. ProjectSetting에 진입하여, Graphic -> TransparancySortAxis를 설정 해 주어야 한다. 투명 레이어 처리를 하는 작업인데, 우리는 Z축을 기준으로 레이어를 나눠줄 것을 참고한다.
  • 해결은 이 값을 (0,0,-0.1)로 지정을 해 주었다. 마지막 값이 음수여야 z가 커질수록 위로 올라가는 연출이 가능하다.
  1. 이제 각 레이어 층 마다 transform의 z값을 지정해 준다. 이제 숫자가 클 수록 위에 쌓이게 된다.

<2025-07-27 수정> 생각해보니 y축의 값도 지정을 해 주어 y가 앞에 있을 경우도 추가 처리를 해 주니 해결이 되었다. TransparncySortAxis를 (0,0.5,-0.1)로 두었더니, 더이상 이상하게 타일이 깔리는 현상이 사라졌다.
이유를 생각해보면 y축의 값을 받지 않다보니 몇몇 타일들은 y축의 value를 동등하게 생각하여 따로 처리를 안해주다보니 그런 것 같다.

3. 점프구현

이동구현은 간단하지만, 점프를 2D 혹은 2.5D에서 구현하는 작업은 쉬운 작업이 아니였다.

문제 1. 바닥타일을 만들고 플레이어에 jump를 구현하기 위해 바닥타일들에 Collision을 넣었더니, 플레이어가 고정이 되버린다.

  • 파악 : 상황을 보니 isomatric은 여전히 3차원이 아닌 2차원 작업이다. 즉 z축으로 구현을 한다기보다는 다른 방식을 택 하는것이 빠른다.

  • 결론 : Ground는 일단 충돌판정을 하는 Collision - Dynamic 을 사용하면 안된다. 나중에 구역 처리를 위해서라면 Collision의 Trigger만 사용하도록 하자.

문제 2. 이제 Jump를 구현하려 하였지만, 바닥에 collision이 없으니 중력값을 주면 플레이어가 떨어진다.

  • 파악 : 2D에서는 중력이 y좌표로 작동된다. 그 즉슨 우리는 y좌표를 속여서 점프하는 연출을 해 줄 것이다.

문제 3. 이제 Jump에서 착지를 구현 하는 방식에 의문이 들었다.

  • 시도 : 중력을 줬다가 빼는 방식을 사용하였지만, 처음 그 위치에 돌아올 수 없으며, 속도 조절도 안된다.

  • 시도 : Lerp나 Pingpong을 사용해 보려 하였지만, 이는 부드러운 연출이 되지 않는다.

  • 파악 : 부드러운 연출 그래프를 생각해보니 Cos이 생각이 났다. Lerp로 각도를 받아주고, 이를 Cos으로 하면 Cos면적은 1이기 때문에 부드럽게 돌아올 수 있을것이다.

문제 4. 하지만 Lerp특성상 각도가 후반부에 몰려있어 높이가 처음보다 훨씬 떨어져있다.

  • 파악 : Lerp는 중간값을 업데이트 하며 받아오기 때문에, 결국 끝부분에 값이 몰릴 수 밖에 없다. 추가적으로 오류 범위를 정해주어 정지를 할 수 있도록 구현하였다.

  • 해결 : 우리는 새로운 변수 하나를 만들어 플레이어가 얼마큼 올라가고 내려갔는지 저장을 해 줄것이다. 이제 호출이 되고 난 후 이 값이 다시 0미만이 되었을 시점에, 높이를 0으로 맞추어 주면 오차가 크게 발생하지 않으며, 이동하면서 점프도 처리가 가능하다

코드 스니펫

    void JumpAction()
    {
        jumpdeg = Mathf.Lerp(jumpdeg, 2.0f, Time.deltaTime * playerSpeed);
        jumpheight += Mathf.Cos(jumpdeg);
        transform.position += new Vector3(0, Mathf.Cos(jumpdeg) / 10.0f, 0);
        if (jumpheight < 0.0f)
        {
            jumpheight = 0.0f;
            jumpdeg = 0.0f;
            _isJumping = false;
        }
    }

4. 벽 충돌 로직

문제 : 벽에 플레이어가 가까이 붙기도 전에, 충돌하여 진입할 수 없는 빈 공간이 생겼다.

  • 시도 : Collider의 offset도 조정해 보았지만, 이는 해결 방법이 아니였다. (이동만 될 뿐이지 간격은 동일하게 존재한다.)

  • 파악 : 플레이 테스트를 해 보면 충돌범위를 확인해보니, 해당 벽 옆에 충돌을 하는게 아닌, 그 위쪽이나 왼쪽 블럭에서 플레이어의 머리부분이 충돌하여 발생하는 문제였다.

  • 해결 : 다양한 방식 중 플레이어의 히트판정을 몸 전체가 아닌 "몸통부분" 에만 주었다. 즉 머리부분이 충돌을 하는것처럼 보이지 않고, 실제 몸통부분이 충돌이 될 시 충돌판정이 되어 훨씬 자연스럽게 벽 옆부분에 붙는 연출이 가능하였다.

마무리

오늘은 새로운것을 시도하기위해 isomatric 타일들을 가져와서 여러 작업들을 하며 트러블 슈팅을 하였다. 여러 고민들을 많이 해 보았지만, 생각을 다양하게 하며 구현을 하다보니, 결국 오늘 생각한 문제들을 해결 할 수 있었다.

profile
코딩공부용

0개의 댓글