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

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

우선 해당 주차의 내용을 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개의 댓글