잼 프로토타입에서 스팀 출시작으로
7월 말 게임잼을 마감할 당시 목표는 점수 가시화(P1)와 캐리어 내부 표현(P3) 정도였다. 하지만 그 두 가지를 진행하는 과정에서 프로젝트의 성격 자체가 완전히 바뀌었다. 단순 잼 출품작이 아니라 스팀에 정식 출시하는 상용 게임으로 목표가 상향되었기 때문이다.
이에 따라 단순히 기능을 덧붙이는 것을 넘어, 상표권 정리·다국어 폰트 파이프라인·스토어 메타데이터 등 '게임 코드가 아닌 출시에 필요한 영역'에 많은 공수가 투입되었다.
| 항목 | 2026-07 잼 마감 시점 | 2026-08 스팀 심사 시점 (v0.2.0) |
|---|---|---|
| 버전 / 상태 | v0.1.0 (달맞이잼 제출) | v0.2.0 (스팀 스토어 심사 제출) |
| 맵 구성 | 단일 방 (1종) | 4종 (집, 숙소, 회사 평소/명절) |
| 난이도 코스 | 5단계 (튜토리얼 ~ 난장판) | 13단계 (CHAOS 및 맵별 코스) |
| 등장 아이템 | 31종 | 48종 |
| 현지화 | 한국어 단일 | 4개 언어 (한·영·일·중 간체, 583줄) |
| 업적 / 랭킹 | Firebase REST 랭킹 | 스팀 업적 14종 · Firebase 19판 |
이름과 상표권, 그리고 폰트 파이프라인
9시 KTX에서 9시 OverPack으로
초기 프로젝트명이었던 9시 KTX는 공공 상표권을 직접 침해할 소지가 있었다. 정식 출시를 위해 게임 내의 KTX, 코레일톡, 카카오톡 등의 명칭을 가상 열차, 가상 항공편, '키톡' 메신저로 전면 교체했다.
이 과정에서 코드에 직접 작성되어 있던 한국어 문자열을 전부 strings.csv로 추출했다. 현재 한국어, 영어, 일본어, 중국어(간체) 4개 언어로 583줄의 텍스트가 관리된다.
다국어 서브셋 폰트 파이프라인
현지화 과정에서 예상치 못한 문제가 발생했다. 기본 사용 폰트에 한자가 포함되어 있지 않아 일본어와 중국어 텍스트가 네모(□)로 출력되는 현상이었다. 전체 한자 폰트를 통째로 넣기에는 파일 용량과 빌드 부담이 컸다.
이를 해결하기 위해 번역 CSV에 실제로 등장하는 글자만 추출하여 경량 서브셋 폰트를 자동으로 굽는 파이프라인 스크립트(make_font.py)를 제작했다. 이제 CSV에 새로운 문장이 추가되면 폰트도 함께 빌드된다. 현지화는 단순 텍스트 번역이 아니라 폰트·빌드·렌더링이 결합된 파이프라인 작업임을 체감했다.
방 하나에서 4개의 맵으로 확장
규칙을 복잡하게 늘리는 대신, 동일한 인벤토리 패킹 규칙이 서로 다른 공간과 상황에서 어떻게 다르게 작용하는가를 보여주고자 했다. 이에 따라 맵을 4개로 확장했다.
| 맵 | 상황 | 2막 (적재 무대) | 퇴장 연출 |
|---|---|---|---|
| 집 | 늦잠 잔 여행 당일 | 골목 택시 트렁크 | 택시가 골목을 빠져나감 |
| 숙소 | 체크아웃 직전 호텔 | 벨보이 카트 | 엘리베이터 문 닫힘 연출 |
| 회사 (평소) | 밤 9시 퇴근 | 비품 창고 캐비닛 정리 | 사무실 문 닫고 소등 |
| 회사 (명절) | 선물세트 받고 귀성 | 지하 주차장 자차 트렁크 | 차가 램프를 타고 출차 |
필수품과 금지물품의 분리 (TripProfileSO)
맵이 늘어나면서 '꼭 챙겨야 할 물건'의 책임을 난이도가 아니라 여행 성격(TripProfileSO)으로 이관했다. 국내 여행이나 일상 퇴근길에서 여권이나 회사 비품은 챙기면 안 되는 금지 물품이다. 난이도는 제한시간과 감점 배율만 담당하도록 역할을 엄격히 분리했다.
무대가 스스로 연출을 아는 구조 (IDepartureAct)
맵마다 엔딩 연출이 달라지면서 GameDirector에 분기문이 누적되는 문제가 생겼다. 이를 해결하기 위해 무대 오브젝트가 스스로의 퇴장 연출을 수행하는 IDepartureAct 인터페이스 구조로 전환했다.
난장판 (CHAOS) 모드
HARD와 동일한 코스이지만 방이 이미 어질러져 있고, 지나갈 때 물건이 튀며, 가방이 터질 때의 물리 반응이 1.8배 강하게 일어난다. 가구 배치는 런타임 검증을 위해 유지하고, 아이템의 초기 상태와 물리 계수만 조정해 규칙 추가 없이 난이도를 끌어올렸다.
2막 무대별 화물과 수직 격자 캐비닛
막 2 화물을 씬이 결정하는 구조
회사 맵 평소 모드의 2막이 호텔용 벨보이 카트와 여행 가방을 그대로 쓰던 문제를 해결하기 위해, 씬별 설정 구조체 TrunkStageSetup을 도입했다.
/// <summary>막 2 무대는 씬마다 다르다 — 화물·격자·캐리어 포함 여부를 씬이 준다.</summary>
public struct TrunkStageSetup
{
public string[] LoadItemIds;
public int GridWidth, GridHeight;
public Vector2Int[] BlockedCells; // 스페어타이어 자리 — 카트·캐비닛에는 없다
public bool CarriesSuitcase; // 창고 정리에는 캐리어가 끼지 않는다
public string PromptSuffix;
}
수직 격자 — 앵커 설계가 만든 효과
비품 창고 2막에서는 위로 여는 트렁크 대신 양문형 철제 캐비닛에 물건을 수납한다. 기존 패킹 코드가 칸 좌표를 앵커 기준 상대 좌표로 계산하고 있었기 때문에, 격자 로직은 단 한 줄도 수정하지 않고 앵커 회전만 90도 세워 수직 격자를 완성할 수 있었다.
// 앵커를 눕히면 트렁크, 세우면 선반이 된다 — 격자 계산은 그대로다.
packOrigin.rotation = Quaternion.LookRotation(Vector3.up, Vector3.right);
station.Configure(packOrigin, itemRoot, cellRoot, leftPivot, viewPose,
SupplyCellSize, SupplyCellSize, CabinetOpenAngle);
station.ConfigureDoors(rightPivot, Vector3.up, upright: true); // 두 짝 문은 서로 반대로 돈다
캐리어 내부 3D 물품 렌더링 (P3 완료)
캐리어 내부의 단색 컬러 블록을 실제 3D 물품 프리팹으로 교체했다. 다만 모델만 배치하면 차지하는 칸 영역이 불분명해지므로, 바닥을 덮는 얇은 발자국 판과 그 위에 얹히는 실제 3D 모델의 2단 구조로 시인성을 확보했다.
트러블슈팅과 3D 디버깅의 교훈
스팀 스토어 심사 및 10월 넥스트 페스트(Next Fest) 등록, 그리고 맵 확장 과정에서 마주친 주요 이슈들이다.
- 스팀 페스트 명칭 불일치: 스토어 페이지 이름과 앱 메타데이터가 분리되어 있어 축제 도구에 옛 이름이 노출됨 → 메타데이터 Publish 완료로 해결.
- Windows 빌드 Postprocess 실패: 에디터 도메인에 잔류한 임시 어셈블리가 원인 → 빌드 전 도메인 리셋 파이프라인 정리.
- 버전 상수 분산: 코드 여러 곳에 흩어져 있던 버전 표기를 단일 원천 상수로 통합.
| 증상 | 원인 및 해결 |
|---|---|
| 자차 퇴근인데 택시 경적이 울림 | 명절 맵에 연출 컴포넌트 누락으로 기본값(택시) 폴백 발생 → 전용 연출 바인딩 |
| 2막 진입 시 화면이 텅 빔 | 사무실에서 지하 10m로 카메라가 보간 이동하며 허공 노출 → 암전 시 순간이동 처리 |
| 창고 수납장이 보이지 않음 | 테두리 통판 높이가 격자와 같아 내부를 가림 → 모델 규격 및 렌더 큐 수정 |
| 퇴장 시 트렁크 뚜껑만 보임 | 엔딩 카메라가 차량 뒤 0.4m에 위치 → 카메라 오프셋 및 화각 재조정 |
| 금지 물품이 체크리스트에 뜸 | 2막 미리보기에서 금지 목록 필터링 누락 → 채점 및 UI 표시 파이프라인 일원화 |
현재 상태와 향후 계획
현재 0.2.0 버전으로 4개 맵, 13개 난이도 코스, 48종 아이템, 14종 업적, 4개국어 지원이 완성되었으며, 스팀 상점 페이지는 공개 준비 중(Coming Soon 및 10월 넥스트 페스트 예정)이다.
향후 10월 초 데모 빌드 제출(심사 3~5영업일 소요), HARD 난이도 밸런스 실측 후 개방, 맵 선택 카드 UI 다듬기, 사운드(BGM) 보강을 차례로 진행할 예정이다.