FPS Arena는 브라우저에서 도는 게임이라 폰에서도 열립니다. 열리기는 하는데, 실제로 폰에서 해 보면 게임이 아니었습니다. 제보가 세 개 왔고 원인이 셋 다 달랐습니다.

1. 조이스틱을 끌면 총이 나간다

이동하려고 왼쪽 조이스틱을 끄는 동안 총이 계속 발사됐습니다. 화면을 아무 데나 만져도 나갔습니다.

처음 짚은 원인은 Godot 설정이었습니다. emulate_mouse_from_touch 가 기본으로 켜져 있어서 터치가 가짜 마우스 좌클릭을 만들고, 사격이 좌클릭에 묶여 있으니 당연한 결과로 보였습니다. 껐습니다. 그런데 안 고쳐졌습니다.

가짜 클릭을 만드는 게 Godot이 아니라 브라우저였습니다. 모바일 브라우저는 터치 이벤트를 처리한 뒤 호환성 마우스 이벤트(mousedown)를 따로 발생시킵니다. 엔진 입장에서는 진짜 마우스가 눌린 것과 구분되지 않으므로, 엔진 설정으로는 막을 방법이 없습니다.

그래서 규칙 자체를 바꿨습니다.

var mouse_fire := Input.is_action_pressed("fire") and not touch_mode

터치 조작이 켜져 있으면 마우스 입력을 통째로 버립니다. 터치 기기에서 들어오는 마우스는 정의상 전부 합성된 것이므로, 브라우저가 어떻게 동작하든 이 규칙은 깨지지 않습니다.

플랫폼이 무엇을 보내주느냐에 기대는 대신, 그 입력이 존재할 수 없는 상황을 정의하는 편이 튼튼합니다.

2. 버튼을 누르면 화면이 돈다

조이스틱으로 이동하면서 오른쪽 버튼을 누르면 시점이 홱홱 돌아서 정신이 없다는 제보였습니다.

이건 제 설계 때문이었습니다. 엄지 하나로 쏘면서 조준까지 하라고, 사격 버튼을 누른 손가락이 그대로 시야 조작 손가락을 겸하게 만들어 뒀습니다. 의도는 좋았는데, 버튼을 탭할 때 엄지가 몇 픽셀만 흔들려도 그게 전부 시야 회전으로 들어갔습니다.

  • 이동 임계값을 뒀습니다. 손가락이 16px 넘게 움직이기 전까지는 시야를 돌리지 않습니다.

탭은 이제 화면을 흔들지 않고, 의도적으로 끌면 그때부터 돕니다.

  • 터치 감도를 0.55 에서 0.34 로 낮췄습니다. 손가락은 마우스보다 한 번에 크게 움직이는데

같은 계수를 쓰고 있었습니다.

3. 총을 어떻게 바꾸는지 모른다

"총 변경은 어떻게 해?" 라는 질문을 받았습니다. 버튼은 있었습니다. "교체" 라고 적힌 작은 원이었습니다.

문제는 그게 무기 버튼인지 알 수 없다는 것이었습니다. 눌러도 뭐가 바뀌었는지 화면에 안 나타나고요. 그래서 버튼에 지금 든 무기 이름을 띄웠습니다. VK-47, 브리처, 나이프. 누르면 다음 무기로 넘어가고 글씨가 바로 바뀝니다.

라벨 하나 바꾼 게 전부인데, 이제 그 버튼은 설명이 필요 없습니다.

4. 글씨가 안 보인다

게임 화면은 1280x720 기준으로 만들어져 폰 화면에 축소돼 들어갑니다. 그러니 데스크톱에서 적당하던 18px 글자가 폰에서는 물리적으로 훨씬 작아집니다.

터치 기기에서 UI 전체를 1.45배로 키웠습니다. 그리고 키우자마자 레이아웃이 여러 군데 깨졌습니다.

깨진 것원인
좌상단 안내문이 점수판과 겹침글자가 커져 가로로 화면 가운데까지 밀고 들어감
체력 막대가 인체 도식 위에 겹침막대는 배율을 탔는데 도식은 안 탐
탄약이 조준 버튼과 부딪힘데스크톱의 우하단 자리를 터치에서는 버튼이 차지함

배율을 한 군데(_ui_scale)에서 관리하는데도 깨진 이유는, positionsize 를 직접 주는 요소들이 그 배율을 안 타기 때문이었습니다. 상자를 만들어 주는 헬퍼를 거치는 것들만 자동으로 커지고, 손으로 좌표를 박은 것들은 제자리에 남았습니다.

안내 문구도 기기별로 갈랐습니다. 폰에서 "좌클릭 사격 · Tab 점수판" 은 의미가 없을 뿐 아니라, 자리만 차지해서 점수판을 가립니다.

진짜 원인은 하나였다

셋 다 원인이 달랐지만 공통점이 있었습니다. 저는 모바일 화면을 한 번도 본 적이 없었습니다.

터치 조작 코드를 쓰고, 논리를 확인하고, 데스크톱에서 테스트하고, 배포했습니다. 그 사이에 모바일 UI 가 실제로 어떻게 보이는지는 확인하지 않았습니다. 제보가 오기 전까지는 문제가 있는지도 몰랐고, 제보가 온 뒤에도 화면을 안 보고 코드만 읽어서 첫 원인을 잘못 짚었습니다.

그래서 데스크톱에서 모바일 UI 를 강제로 켜는 통로(--touchui)를 만들었습니다. 이걸로 찍어 보니 위 표의 세 가지가 한 장에 다 보였습니다. 제보로 받은 건 "글씨가 작다" 하나였는데, 겹침 두 개는 그 화면을 보고 나서야 알았습니다.

코드가 맞는지는 읽어서 알 수 있지만, 화면이 맞는지는 봐야만 압니다.