LiquidPvP는 제가 처음 Unity를 잡은 프로젝트입니다. 만들어 놓고 한동안 손을 못 댔습니다.
기능이 모자라서가 아니었습니다. 한 번 고치고 확인하는 데 드는 시간이 길어서 열어 보기가 싫어졌습니다. 빌드가 무겁고 반복이 느리면, 고치고 싶은 것이 있어도 "오늘은 됐다"가 됩니다.
Godot으로 전면 재작성했습니다.
다시 쓰되 다시 정하지는 않았습니다
옮기면서 규칙을 새로 만들지 않았습니다. 로직과 수치는 옛 프로젝트에서 그대로 가져왔습니다. 점수표, 연쇄 보너스 같은 것들입니다.
이걸 지키는 게 중요했습니다. 엔진을 옮기면서 게임까지 바꾸면, 나중에 뭔가 이상할 때 엔진 때문인지 규칙을 바꿔서인지 구분할 수 없습니다. 옮기는 동안에는 옮기기만 합니다.
방울은 블록이 아닙니다
이 게임의 성격은 여기서 나옵니다. 같은 색 넷 이상이 붙으면 터지고, 터진 자리 위가 무너져 다시 넷이 되면 연쇄입니다. 여기까지는 흔한 낙하 퍼즐입니다.
다른 것은 방울이 액체라는 점입니다. 같은 색끼리 닿으면 동그라미 두 개가 아니라 하나의 덩어리로 합쳐집니다. 표면장력이 있는 것처럼요.
처음에는 원을 그리고 사이를 이어 붙이는 방식으로 만들었습니다. 목처럼 이어진 부분, 납작해지는 연출, 그림자와 광택을 하나하나 손으로 그렸습니다.
메타볼 셰이더로 다시 만들면서 그걸 전부 지웠습니다. 각 칸이 주변에 퍼뜨리는 값을 더해서 일정 값을 넘는 곳을 칠하면, 합쳐지는 모양이 저절로 나옵니다. 같은 색끼리만 더하니 다른 색은 섞이지 않습니다. 출렁임은 그 위에 좌표를 살짝 비트는 것으로 얹었습니다.
손으로 그리던 보조 함수 여럿이 셰이더 한 장으로 없어졌습니다.
염색조
떨어지는 길목에 색을 바꾸는 통이 있습니다. 통과하면 방울 색이 바뀝니다.
이게 있으면 "지금 오는 색"만 보고 판단할 수 없습니다. 어디로 떨어뜨리느냐가 색까지 정합니다. 그리고 이 통은 쌓인 높이를 따라 오르내려서, 판이 진행될수록 통과시킬 수 있는 자리가 달라집니다.
온라인 대전에 서버를 두지 않았습니다
방 번호로 붙는 온라인 대전을 넣었습니다. 전용 서버는 없습니다.
먼저 P2P를 검토했는데, 오가는 데이터를 세어 보니 수십 바이트였습니다. 격자 128자, 염색조 8자, 점수. 이 정도면 실시간 채널로 주고받아도 충분합니다. P2P를 쓰면 엔진에 네이티브 확장을 붙여야 하는데, 얻는 것이 없는 복잡함이었습니다.
내 보드만 계산하고 상대 보드는 받은 스냅샷을 그립니다. 방 번호가 곧 채널 이름이라 인터넷 너머로도 붙습니다. 벙개벙개가 이미 쓰던 것을 그대로 씁니다 — 새 계정도, 새 요금도 없습니다.
검증은 인스턴스 둘을 동시에 띄워서 했습니다. 상대 탐색, 상태 36회 양방향 교환, 상대 점수 미러링, 공격이 방해물로 전달되는 것까지 확인했습니다.
평문으로 들어 있던 접속 정보
안드로이드 빌드를 내면서 확인한 것입니다. APK 압축만 풀면 접속 설정이 평문으로 읽혔습니다.
값을 인코딩해서 코드로 굽고, 평문 파일은 빌드에서 제외했습니다. 재빌드한 APK에서 평문이 검색되지 않는 것을 확인했습니다.
다만 이건 난독화이지 암호화가 아닙니다. 마음먹고 뜯으면 나옵니다. 실제 방어선은 서버 쪽 접근 규칙이고, 이건 그 앞에 둔 잠금장치 정도입니다. 그 한계를 문서에 적어 뒀습니다 — 적어 두지 않으면 다음에 이걸 보는 사람이 "암호화돼 있으니 괜찮다"고 생각합니다.
남는 것
재작성을 결정할 때 근거가 "엔진이 무겁다"였습니다. 기능 목록으로는 정당화되지 않는 이유입니다. 옮겨서 새로 얻는 기능이 없으니까요.
그런데 결과적으로 33커밋 만에 처음부터 온라인 대전과 안드로이드 빌드까지 왔습니다. 손이 가느냐가 결국 기능보다 크게 작용했습니다.