모래게임 Sandrop 37
오늘 한 일
- v1.3.0 준비 — 별점 요청, 클라우드 저장 안내 시점 조정
- 게임 화면 버벅임을 재서 고침 (한 프레임 30.5 → 20.6ms)
- 다시하기가 계측에서 빠지던 문제 수정
막힌 부분
별점은 직접 못 받는다 — 스토어 카드를 부르는 게 전부다
앱 안에 별점 요청(인앱 리뷰)을 넣으려다 알았다. 앱이 자기 화면으로 별점을 받는 건 안 된다. 스토어가 자기 별점 카드를 대신 띄우고 점수도 스토어가 가져가기 때문에, 앱은 그 카드가 떴는지도 몇 점이 매겨졌는지도 알 수 없다. 부르는 횟수도 스토어가 제한해서, 불러도 조용히 아무것도 안 뜰 수 있다.
게다가 “재밌으셨나요?”로 먼저 걸러 좋다는 사람만 별점 카드로 보내는 것은 정책 위반이다.
그래서 앱이 할 수 있는 건 하나뿐이었다 — 좋은 순간에, 조건 없이, 스토어 카드를 한 번 부른다.
- 제약이 셋이면(화면 못 만듦·결과 못 봄·선별 금지) 설계가 하나로 정해진다. 고를 게 없으면 고민할 것도 없다
- 불러도 안 뜰 수 있으니 설정에 언제든 리뷰를 쓸 수 있는 통로를 따로 뒀다. 막힐 수 있는 길이 유일하면 안 되니까
물어볼 시점은 도달 분포가 정했다
처음엔 50탄으로 잡았다. 충분히 해 본 사람에게 묻는 게 맞아 보였다.
그런데 어제 본 도달 분포가 29·38·150이었다. 50탄 기준이면 셋 중 하나에게만 묻는다. 30탄이면 둘이고 곧 셋이다.
- 리뷰는 물어볼 수 있는 사람 수가 기준을 정한다. “충분히 해 본 사람”은 그다음 조건이다
- 어제 데이터를 안 봤으면 50으로 냈을 것이다
재는 도구가 앱을 못 보고 있었다
버벅인다는 이야기가 있어 프레임을 쟀다. 30초를 플레이했는데 25프레임으로 나왔다. 초당 한 장이라는 소리라 말이 안 된다.
원인은 도구였다. 이 게임은 화면에 직접 그려서 안드로이드 기본 렌더러를 거치지 않는데, 쓰던 도구는 그 렌더러만 본다.
그럼 앞서 몇천 프레임이 잡힌 건 뭐였나. 하단 배너가 떠 있을 때만 화면 합성 방식이 바뀌어 집계됐던 것이다. 배너가 떴냐 안 떴냐에 따라 재는 대상 자체가 달랐다.
앞서 잰 것을 전부 버리고, 앱이 직접 알려주는 프레임 시간을 쓰기로 했다.
- 숫자가 상식과 어긋나면 대상이 아니라 도구를 의심한다
- 도구가 무엇을 보고 무엇을 못 보는지 모르면 그 숫자로 판단하면 안 된다
프레임 수를 줄였더니 더 끊겼다
120Hz 화면이라 초당 120번 다시 그리고 있었다. 모래 게임에 그만큼 필요 없으니 60번으로 걸렀다.
평균은 좋아졌는데 튀는 프레임이 더 나빠졌다. 상위 10%가 28ms에서 48ms가 됐고, 화면은 뚝뚝 끊겨 보였다.
일을 절반으로 나눈 게 아니라, 안 하는 프레임과 두 배로 몰아서 하는 프레임으로 갈라놓은 것이었다.
- 되돌렸다. 횟수를 줄이는 건 값을 옮기는 것이지 없애는 게 아니다
- 한 프레임에 30ms가 들면 초당 몇 번을 그리든 매끄러울 수 없다
다른 판끼리 비교하고 결론 낼 뻔했다
고친 것과 안 고친 것을 나란히 쟀다. 새 방식이 이겼다.
그런데 두 번의 플레이가 서로 다른 판이었다. 하나는 어려움, 하나는 보통이었다. 판마다 통과 색의 개수가 달라 비용이 다르다.
지나간 판을 다시 할 수 있게 열고, 같은 74탄으로 다시 쟀다. 그제야 비교가 됐다.
- 조건이 다른 둘을 비교하면 숫자가 아무리 예뻐도 아무 말도 안 하는 것이다
- 조건이 다른 걸 놓쳤으면 그대로 기록에 남길 뻔했다
캔버스를 미리 구워 두고 잘라 붙였다
그림 영역을 칸마다 하나씩 그리고 있었다. 64×64니까 프레임마다 4096번이다.
완성된 그림은 판이 끝날 때까지 안 변한다. 변하는 건 어디까지 찼나뿐이다. 그리고 한 열의 채움은 바닥부터 연속이라, 한 열이 “안 찬 위 한 덩어리 + 찬 아래 한 덩어리”로 끝난다.
그래서 판에 들어올 때 완성본을 한 장 만들어 두고, 프레임마다 열별로 잘라 붙이게 바꿨다. 4096번이 130번쯤이 됐다.
한 프레임이 30.5 → 20.6ms가 됐다.
- 변하지 않는 것을 매번 다시 만들고 있지 않은지 본다
- 데이터의 구조가 방법을 정해 준다. 열이 연속이라는 사실이 없었으면 이 방법이 안 나온다
배너 하나가 8ms였다
남은 값을 더 찾으려고 배너를 꺼 봤다. 20.6ms가 10~15ms로 떨어졌다.
배너는 앱이 아니라 시스템이 그리는 화면이라, 그게 떠 있으면 게임 화면을 한 번 더 베껴야 한다. 그 값이 매 프레임 든다.
오늘 하루 종일 캔버스를 뜯어고쳐 번 것이 10ms인데, 배너 하나가 8ms를 먹고 있었다.
- 남기기로 했다. 광고 수익과 부드러움을 저울에 올리는 문제고, 기술로 정할 것이 아니다
- 큰 값이 예상 밖에 있을 수 있다. 고칠 곳부터 정하고 재면 그걸 못 본다
다음 최적화는 할 게 없었다
안 변하는 부분은 다시 안 만들게 하자는 안이 있었다. 손대기 전에 대상을 세어 봤다.
캔버스도, 아이템 바도, 튜토리얼 표시도 매 프레임 값에 의존했다. 상단 표시줄까지 그랬다 — 벨트가 꽉 찼는지에 따라 버튼이 생겼다 없어진다.
프레임과 무관한 건 배너뿐인데 그건 이미 다시 안 만들고 있었다.
- 접었다. 다 구독해야 하면 지금과 같은 범위가 다시 만들어진다
- 세어 보기 전에 “저긴 안 변할 것”이라고 말한 게 오늘 두 번째 헛짚음이다
다음에 할 일
- v1.3.0 내부 테스트에 올리고 확인 뒤 승격
- 남은 그리기 비용이 어디서 나는지 하나씩 꺼보며 재기
- 100탄씩 추가 배포 — 다음 주 착수
- 며칠 뒤 레벨별 도달 분포 확인
- 클라우드 저장 연동률 확인
- 크래시·ANR, 광고 노출 수 확인
- 도안 추가 검토
- 광고 제거 상품 — 리텐션 보고 판단