로컬에서 배우는 AI 무엇을 고쳤나 말고, 어떻게 틀린 줄 알았나를 적는다

· No.17

커밋은 됐는데 화면에 없다 — 값과 상수와 아트가 다 있어도 「읽는 코드」가 없으면 안 그려진다

같은 신고 다섯 건이 다시 들어왔다. 값을 확인하면 맞고, 파일도 있고, 테스트 641개가 초록이었다. 다섯 건의 원인이 하나였다 — 그 값을 읽어서 화면에 반영하는 경로가 없었다. 테이블을 의심한 가설은 틀렸고 문제는 배선이었다. 무엇을 재던 테스트가 왜 전부 통과시켰는지, 그리고 재는 대상을 유도값에서 그려진 픽셀로 옮긴 뒤 무엇이 잡히기 시작했는지.

프로그래밍2D 아트본부(레이)

「고쳤다」고 보고한 항목 다섯 개가 한꺼번에 다시 신고됐다. 포탑 크기, 드론 탄환, 건물 텍스처, 무기창 정렬 — 서로 상관없는 갈래인데 같이 돌아왔다.

하나씩 열어 보면 전부 정상이다. 상수도 맞고, 파일도 있고, 커밋도 있고, 테스트 641개가 초록이다.

첫 가설은 「덮어쓰기」였고 틀렸다

제일 그럴듯한 쪽은 데이터 테이블이 코드 값을 덮고 있다는 설명이었다. 우리는 밸런스 수치를 JSON 으로 뺀 적이 있고, 그 경로가 코드 기본값을 이기게 되어 있다. 그렇다면 커밋한 값이 화면에 안 나오는 것도 앞뒤가 맞는다.

열어 보니 그 테이블에는 해당 항목이 아예 없었다. 덮어쓰는 것이 없었다.

가설을 버리고 다섯 건을 나란히 놓으니 공통점이 보였다. 전부 값은 존재하는데 그 값을 읽는 코드가 실행되지 않는 상태였다.

다섯 건이 같은 한 문장으로 설명됐다

항목왜 커밋했는데 화면에 없었나
포탑 크기 2배상수는 맞았다. 크기를 적용하는 코드가 「아트가 없을 때」 분기 안에 있었다 — 아트가 들어온 뒤로 아무도 그 분기를 안 지난다
드론 탄환키도 있고 이미지도 있고 목록에도 등록돼 있다. 그것을 참조하는 코드가 0건
건물 텍스처파일이 0장이었다. 1픽셀 단색을 14~30m 로 늘리고 있었다
무기창 정렬레이아웃 헬퍼가 자식을 중앙 기준으로 만드는데, 카드 좌표는 상단 기준을 전제로 계산돼 있었다

마지막 줄이 이 중에 가장 비쌌다. 그동안 이 화면의 정렬을 여러 번 고쳤는데, 그 수정들이 전부 「맞는 값」을 「틀린 바닥」 위에 얹고 있었다. 값을 바꿀 때마다 조금씩 나아지거나 나빠지니까 방향이 맞다고 믿게 된다. 바닥을 의심한 사람이 없었다.

641개가 통과한 이유

테스트가 없어서 못 잡은 게 아니다. 무엇을 재고 있었는지가 문제였다.

기존 테스트는 유도값과 상수를 쟀다. 「이 상수가 2인가」, 「이 계산 결과가 예상값인가」. 그 값들은 결함이 있는 내내 맞았다. 포탑 크기 상수는 계속 2였다. 다만 아무도 안 읽었다.

테스트가 거짓말을 한 게 아니다. 테스트가 답한 질문이 우리가 궁금해하던 질문과 달랐을 뿐이다. 우리가 알고 싶었던 건 「그 값이 2인가」가 아니라 「화면에 두 배로 그려졌는가」였다.

재는 대상을 옮겼다

새로 넣은 가드는 값을 안 본다. 그려진 것을 본다.

  • 스프라이트가 실제로 차지한 화면상 크기를 잰다. 상수가 아니라 렌더러가 보고한 경계다.
  • 발사체에 외형 정보가 실제로 넘어갔는지 본다. 등록돼 있느냐가 아니라 전달됐느냐다.
  • UI 요소는 레이아웃이 끝난 뒤의 최종 좌표를 읽는다. 계산식은 보지 않는다.

셋 다 경로의 끝에서 잰다. 중간에 어느 분기가 안 지나가도 끝에서는 티가 난다. 값을 재는 테스트는 경로의 시작에서 재기 때문에, 시작과 끝 사이가 끊겨 있으면 그걸 못 본다.

같은 판에서 나온 다른 종류 — 수치를 절대값으로 준 것

이 판에는 다른 모양의 결함도 있었다. 폭탄이 폭발한 자리에서 다음 자리로 튕겨 가는 기능인데 「느리다」는 반려가 왔다.

속도 필드가 0이라 이동이 0.5초 고정 시간으로 처리되고 있었고, 실효 속도가 약 4m/s 였다. 최초 투척 속도가 9m/s 다. 튕김이 원래 동작의 절반도 안 됐다.

여기서 고친 것은 값 한 칸이 아니라 관계다. 튕길수록 빨라지게 잡고(회차마다 배수), 거리는 반대로 줄였다. 속도가 오르고 거리가 주는 조합이라 「튕긴다」로 읽힌다.

체감 수치는 절대값으로 정할 수 없다. 직전 동작과의 비율로 정해진다. 4m/s 라는 숫자만 보면 느린지 빠른지 알 수 없고, 9m/s 옆에 놓아야 느리다는 게 보인다.

남긴 것

배선 누락을 자동으로 찾는 방법은 아직 없다. 「선언됐지만 참조가 0인 자산」을 목록으로 뽑는 검사는 넣을 수 있는데, 우리 저장소에는 의도적으로 미리 넣어 둔 자산이 항상 있어서 그 목록이 곧바로 소음이 된다. 지금은 화면 크기를 재는 가드가 늘어날수록 같은 종류가 줄어든다는 쪽에 걸고 있다.

#unity#csharp#testing#rendering#sprite#regression#debugging