유니티 어드벤처 게임 개발 중 겪은 입력 처리 오류와 해결 과정
게임을 만들다 보면 잘 작동하던 기능이 어느 순간 꼬여서 안 되는 경우가 있다. 특히 유니티에서 입력 처리와 오브젝트 상호작용을 동시에 다룰 때는 흔히 발생하는 문제인데, 이번에 내가 직접 겪었던 사례를 정리해보려고 한다. 비슷한 상황에서 헤매는 분들에게 작은 힌트가 되었으면 한다.

버튼은 눌리는데 코드가 안 도는 상황
게임 속에서 캐릭터가 선택지를 고르는 토론 장면이 있다. 버튼을 누르면 색상은 진하게 변하고 눌린 것처럼 보이는데, 정작 Update 안의 코드가 실행되지 않는 현상이 발생했다. 눈으로는 버튼이 눌렸는데 아무 반응이 없으니 처음에는 UI 쪽 문제인 줄 알았다. 그런데 확인해보니 버튼 자체는 정상적으로 눌리고 있었고, 문제는 내가 작성한 입력 처리 방식에 있었다.
나는 입력을 체크할 때 InputManager 안에 GetSubmitPressed()라는 함수를 만들어 썼다. 이 함수는 버튼이 눌린 순간 true를 반환하고, 그 직후 false로 초기화한다. 즉, 한 프레임 동안만 true를 주고 다시 꺼버리는 방식이다. 이 구조 자체는 흔히 쓰이는 패턴이지만, 여러 오브젝트에서 동시에 확인하면 문제가 생긴다. 첫 번째로 이 함수를 호출한 객체만 true를 받고, 나머지는 false만 받아버리기 때문이다. 결과적으로 버튼 색상은 바뀌었는데 로직은 안 도는 것처럼 보였다.
저장과 로드 이후 꼬이는 bool 값
또 하나의 문제는 저장과 로드 과정에서 발생했다. 처음 실행할 때는 상호작용이 잘 되는데, 세이브 파일을 불러오면 대화나 아이템 상호작용이 안 되는 경우가 생겼다. 원인은 bool 값이 꼬여서였다. 예를 들어, playerInRange 같은 변수는 플레이어가 범위 안에 들어왔을 때 true로 바뀌어야 하는데, 로드 이후에는 OnTriggerEnter2D가 다시 호출되지 않아서 여전히 false 상태로 남는 경우가 있었다.
이런 경우는 특히 SetActive(true)로 오브젝트를 다시 살려낼 때 자주 일어난다. 이미 캐릭터가 충돌 범위 안에 있는데도 OnTriggerEnter가 다시 실행되지 않기 때문이다. 그래서 저장을 불러온 뒤에는 실제로는 범위 안에 있어도 조건이 false라서 상호작용이 안 먹히는 현상이 발생한다.
흔히 하는 실수, UI와 입력 혼용
또 놓치기 쉬운 부분이 있다. UI 버튼과 게임 로직 입력을 같은 키로 처리할 때 생기는 문제다. 나는 Submit 키 하나로 UI 버튼 색상 변화와 게임 내 오브젝트 상호작용을 동시에 처리했는데, 저장/로드 후에는 EventSystem의 포커스가 달라져서 버튼은 색이 변하지만 로직이 실행되지 않는 상황이 발생했다. 결국 UI 이벤트는 Button.onClick으로만 처리하고, 게임 오브젝트 상호작용은 InputAction 이벤트나 별도의 입력 처리로 분리하는 게 안정적이라는 결론을 얻었다.
해결을 위한 시도와 개선 방법
이 문제들을 해결하기 위해 몇 가지 접근을 했다.
첫째, GetSubmitPressed의 구조를 바꿨다. 지금까지는 호출과 동시에 false로 초기화했지만, 이를 LateUpdate에서만 초기화하도록 변경했다. 이렇게 하면 여러 오브젝트가 같은 프레임 안에서 동시에 true를 확인할 수 있고, 입력이 한쪽에만 소비되는 현상이 줄어든다. 또 다른 방법은 Peek/Consume 구조를 도입하는 것이다. Peek은 단순히 현재 상태만 확인하고, Consume은 true를 반환하면서 상태를 false로 바꾼다. 이렇게 구분하면 입력을 더 명확하게 제어할 수 있다.
둘째, 저장과 로드 이후 bool 값을 보정했다. playerInRange 같은 경우 OnTriggerStay2D를 활용해 범위 안에 있는 동안은 계속 true로 유지되도록 했다. 또 로드 직후에는 Physics2D.OverlapCircle 같은 함수를 써서 실제 플레이어 위치를 다시 확인하고, 변수 값을 초기화했다. 대화창이나 선택지 버튼도 로드 직후에 Select()를 호출해 포커스를 강제로 맞춰주니 훨씬 안정적으로 동작했다.
셋째, UI 이벤트와 게임 입력을 확실히 분리했다. UI 버튼 클릭은 유니티 기본 onClick 이벤트에만 맡기고, 게임 내 오브젝트 상호작용은 InputAction의 performed 이벤트를 직접 받아 처리했다. 이렇게 분리하니 저장과 로드 이후에도 서로 간섭하지 않고 잘 작동했다.
흔히 나오는 질문이자 흔히 겪는 오류
사실 내가 겪은 문제는 특별한 게 아니다. 유니티 커뮤니티를 조금만 찾아보면 비슷한 질문이 정말 많이 올라온다.
1. 버튼은 눌리는데 코드가 안 도는 경우
2. 저장/로드 후에 상호작용이 안 되는 경우
3. 입력을 여러 곳에서 동시에 확인하면 한 쪽만 먹히는 경우
이 세 가지는 초보자부터 중급자까지 누구나 한 번쯤 겪는다. 결국 핵심은 입력 이벤트가 프레임 단위로 어떻게 흘러가는지 이해하고, bool 상태를 세이브/로드에 맞게 관리하는 것이다. 거기에 더해 UI와 게임 입력을 분리하면 대부분의 문제는 해결된다.
정리하며
정리하자면, 내 경우에는 입력 신호가 한 프레임만 true였다가 곧바로 false로 바뀌는 구조 때문에 문제가 꼬였다. 게다가 저장과 로드 이후에는 bool 값과 포커스가 어긋나서 더 심각하게 보였다. 하지만 구조를 조금 수정하고, 상태를 로드 시점에서 재보정해주니 해결할 수 있었다.
앞으로도 이런 문제는 계속 생길 거다. 왜냐하면 게임 개발에서 입력과 상태 관리는 늘 복잡하게 얽히기 때문이다. 다만 이번 경험을 통해, 문제가 발생했을 때 단순히 “버그다”라고만 보지 않고, 입력의 흐름과 상태 동기화를 먼저 점검하는 습관을 들이는 게 중요하다는 걸 느꼈다.
나처럼 어드벤처나 추리 장르 게임을 만들면서 입력 문제에 부딪히는 분들이 있다면, 위에서 정리한 방법들을 차근차근 적용해보길 권한다. 디버깅 로그를 찍고, LateUpdate에서 상태를 리셋하고, 세이브/로드 후 상태를 재확인하는 과정만 거쳐도 훨씬 수월해질 것이다.
이 글은 실제로 내가 겪었던 시행착오를 정리한 것이니, 같은 문제를 겪고 있는 분들에게 작은 참고가 되었으면 한다.
'자연과학, IT, 공학 > IT, 프로그래밍' 카테고리의 다른 글
| 픽셀 퍼펙트 카메라 제대로 쓰는 방법 정리 (7) | 2025.08.18 |
|---|---|
| Swiper loop 버그, 왜 자꾸 끊기고 사라질까? (5) | 2025.08.17 |
| 유니티에서 대각선 이동 속도 문제 해결하기 (6) | 2025.08.17 |
| 유니티 파티클이 작아질수록 깜빡거리는 문제와 해결 방법 (5) | 2025.08.17 |
| UI 캔버스 크기, 왜 이렇게 큰 걸까? (6) | 2025.08.17 |