유니티에서 대각선 이동 속도 문제 해결하기
게임을 만들다 보면 별거 아닌 것처럼 보이는 부분이 오히려 가장 골치 아플 때가 있다. 특히 캐릭터 이동 같은 기본적인 기능에서 예상치 못한 문제가 자주 생긴다. 내가 이번에 정리하려는 건 바로 대각선 이동 속도 문제다. 상하좌우로는 잘 움직이는데, 대각선으로 갈 때만 갑자기 빨라지는 현상 말이다. 이건 많은 사람들이 처음 유니티로 게임을 만들 때 부딪히는 공통적인 문제다.

대각선이 왜 더 빨라질까?
원인은 단순하다. 캐릭터 이동을 처리할 때 보통 입력값을 2차원 벡터로 받는다. 키보드 방향키나 패드 입력을 생각하면 된다. 예를 들어 위쪽 키를 누르면 (0,1), 오른쪽 키를 누르면 (1,0)이 입력된다. 이 값의 길이는 1이다.
그런데 위쪽과 오른쪽을 동시에 누르면 (1,1)이 된다. 이 벡터의 길이를 계산하면 √2, 즉 1.41 정도가 된다. 그러니까 같은 속도를 곱하더라도 상하좌우보다 대각선일 때 이동량이 더 커져 버린다. 결과적으로 캐릭터가 대각선으로 움직이면 실제로 더 빨라지는 것처럼 보이는 거다. 이건 그냥 느낌상 문제가 아니라 수학적으로 실제 좌표가 더 이동하는 거라 반드시 보정이 필요하다.
정규화라는 해결책
이 문제를 해결하는 가장 확실한 방법은 정규화다. 정규화란 벡터의 길이를 무조건 1로 맞추는 작업이다. 방향은 그대로 두고 크기만 1로 맞춰주는 거다. 예를 들어 (1,1)을 정규화하면 (0.7,0.7) 정도로 바뀌고, 길이가 정확히 1이 된다. 이렇게 하면 직선이든 대각선이든 항상 같은 속도로 움직이게 된다.
유니티에서는 벡터 뒤에 normalized라는 속성을 붙이면 쉽게 정규화를 할 수 있다. 입력이 (0,0)일 때도 그대로 (0,0)이 나오기 때문에 따로 조건문을 달지 않아도 된다. 그래서 제일 깔끔한 방법은 그냥 무조건 normalized를 붙여 쓰는 거다.
조건부 정규화라는 방식도 있다
다만 모든 상황에서 무조건 정규화를 쓰는 게 답은 아닐 수도 있다. 어떤 경우에는 입력값의 크기가 1보다 클 때만 정규화를 적용하는 방법도 있다. 예를 들어 상하좌우 입력은 원래 길이가 1이기 때문에 그대로 두고, 대각선 입력처럼 길이가 √2 이상일 때만 보정을 하는 거다. 이렇게 하면 직선 이동은 원래 입력값 그대로 반영되고, 대각선에서만 속도가 보정된다.
이 방식은 아날로그 스틱처럼 세밀한 입력을 다루는 게임에서 특히 유용하다. 예를 들어 스틱을 살짝만 기울였을 때 0.3이나 0.5 같은 값이 들어오는데, 이걸 무조건 정규화하면 항상 1로 바뀌어버려서 입력의 감도가 사라질 수 있다. 그래서 이런 경우에는 조건부 정규화가 더 자연스럽다. 다만 PC 키보드 기준이라면 그냥 항상 정규화를 쓰는 게 가장 단순하고 확실하다.
애니메이션 연동하기
캐릭터가 움직이기만 하면 되는 게 아니라 애니메이션과도 연결이 돼야 한다. 보통 애니메이터에 Speed라는 변수를 만들어 두고, 입력 벡터의 크기를 그대로 전달한다. 입력이 없으면 0, 움직일 때는 1이 들어가서 자연스럽게 애니메이션이 전환된다.
또 캐릭터가 왼쪽으로 갈 때는 얼굴이 좌측을 보고, 오른쪽으로 갈 때는 우측을 보도록 설정해야 한다. 이건 입력 벡터의 x값이 음수인지 양수인지에 따라 스프라이트를 반전시키면 간단하게 해결된다.
어떤 방식을 선택해야 할까?
정리하자면, 항상 정규화를 쓰면 코드가 단순하고 확실하게 문제를 해결할 수 있다. 조건부 정규화는 직선 입력은 그대로 두고 대각선만 보정하는 방식이라 세밀한 제어가 가능하다.
내 경험상 키보드 입력을 주로 쓰는 게임이라면 그냥 항상 정규화를 쓰는 게 답이다. 따로 고민할 필요도 없고, 대각선 속도 문제를 확실하게 잡을 수 있다. 하지만 패드나 모바일 조이스틱처럼 아날로그 입력을 섬세하게 살려야 하는 상황이라면 조건부 정규화가 더 어울린다. 결국 게임의 특성과 입력 방식에 맞게 선택하는 게 가장 좋다.
마무리하며
겉으로 보기에는 단순한 캐릭터 이동이지만, 막상 구현하려고 하면 이런 수학적인 문제들이 숨어 있다. 대각선 속도가 빨라지는 건 피타고라스 정리 때문에 생기는 아주 기본적인 현상이지만, 실제로 코드를 짜면서 경험해 보지 않으면 쉽게 이해하기 어렵다.
이번 글에서 정리한 것처럼 정규화를 적용하면 문제는 간단하게 해결된다. 앞으로 이동 코드를 작성할 때는 방향에 상관없이 캐릭터가 항상 일정한 속도로 움직이도록 신경 쓰는 게 중요하다. 그래야 플레이어가 조작할 때 이질감이 없고, 게임의 완성도가 한층 올라간다.
결국 작은 부분 같지만 이런 디테일들이 모여 게임의 퀄리티를 좌우한다. 나 역시 이 과정을 거치면서 단순한 이동 기능도 그냥 넘기지 말고 꼼꼼하게 다듬어야 한다는 걸 다시 한 번 느꼈다.
'자연과학, IT, 공학 > IT, 프로그래밍' 카테고리의 다른 글
| Swiper loop 버그, 왜 자꾸 끊기고 사라질까? (5) | 2025.08.17 |
|---|---|
| 유니티 어드벤처 게임 개발 중 겪은 입력 처리 오류와 해결 과정 (6) | 2025.08.17 |
| 유니티 파티클이 작아질수록 깜빡거리는 문제와 해결 방법 (5) | 2025.08.17 |
| UI 캔버스 크기, 왜 이렇게 큰 걸까? (6) | 2025.08.17 |
| 유니티 완전 초보가 헷갈리는 부분 정리해봄 (6) | 2025.08.17 |