밤새 AI에게 맡긴 3D 폐차장 게임 (1) 목표 그림과 실제 화면 비교
폐차장에서 부품을 모아 무기를 키우고 밤 웨이브를 버티는 3D 브라우저 게임을 AI가 하룻밤에 만들었어요. 목표 그림과 실제 게임 화면을 나란히 놓고 단계별로 비교해 봤어요.
목차 10개
SCRAPYARD SURVIVOR는 폐차장에서 주운 톱날, 모터, 배터리를 녹슨 파이프에 하나씩 붙여 무기를 키우고, 밤에 몰려오는 고철 좀비와 로봇 개를 버티는 3D 액션 게임이에요. 브라우저에서 돌아가고, 같은 빌드를 Electron으로 감싸 데스크톱 창으로도 띄울 수 있어요.
어느 날 자정에 요구사항 문서를 Claude Code에게 넘기고, 새벽 6시 17분까지 혼자 작업하게 뒀어요. 아래 스크린샷은 이 글을 쓰면서 그 빌드를 다시 켜서 새로 찍은 거예요. 그날 밤 이후로 코드는 한 줄도 바뀌지 않았어요.

| 구분 | 사용한 것 |
|---|---|
| 렌더링 | Babylon.js 8 (WebGPU 우선, 안 되면 WebGL2), TypeScript, Vite |
| 물리 | Havok |
| 3D 에셋 | 이미지 생성 API로 그림, 3D 변환 API로 모델 |
| 캐릭터 애니메이션 | 블렌더를 화면 없이 실행, KayKit CC0 동작 |
| 소리 | 효과음·음악 생성 API, Web Audio |
두 편 중 첫 편이에요. 여기서는 게임 화면을 만든 순서대로 보고, 그림에서 3D 모델을 뽑아 뼈대와 애니메이션까지 입힌 과정은 2편에 적었어요.
목표 그림 6장
첫 요구사항 문서는 Steam에 낼 수준을 목표로 한다는 내용이었고, "이번 작업의 목표는 작동하는 데모가 아니다"라는 문장도 넣었어요. AI는 처음에 폴더에 있던 제 다른 언리얼 프로젝트 기록을 보고 언리얼 프로젝트부터 만들기 시작해서, 바로 멈추고 Babylon.js로 브라우저에서 돌리라는 두 번째 문서를 보냈어요.
같이 넣어 준 목표 그림은 6장이에요. 메인 메뉴, 해 질 녘 폐차장 탐색, 작업대 크래프팅, 밤 전투, 그리고 고철 골렘 보스전 두 장(하나는 군용 폐기장 구역)이에요. 이 그림들도 이미지 생성 AI로 만든 거예요. AI는 이 중에서 폐차장 1구역, 적 2종, 무기 5단계, 밤 웨이브 3번까지를 이번 범위로 잡았어요. 보스와 두 번째 구역은 빠졌어요.
메인 메뉴

목표 그림은 녹슨 철판에 새긴 메뉴와 입구 게이트, 간판이 가득한 장면이에요. 실제 메뉴는 로고와 버튼 네 개(Start Run, Continue, Options, Quit)를 담은 어두운 상자이고, 뒤로 주인공이 서 있는 폐차장 바닥이 천천히 돌아가요. 오른쪽 아래에는 조작키 안내가 붙어 있어요.
새벽 1시 41분 화면에는 뒤쪽에 갈색 상자들이 보여요. 3D 모델이 아직 만들어지는 중이라 자리만 잡아 둔 상자예요. 사진에서 빨간 동그라미 친 곳이에요. 아침에는 이 자리에 철망 울타리와 방호벽 모델이 들어갔어요. 메뉴 모양 자체는 이 사이에 거의 바뀌지 않았어요.
낮 탐색과 부품 줍기

한 판은 오후 3시 30분에 폐차장 입구에서 시작해요. 목표는 "톱날 찾기"와 "작은 모터 찾기"이고, 바닥에 떨어진 부품과 고철은 노란 고리가 빛나는 걸로 표시돼요. 목표 그림은 폐차가 벽처럼 쌓인 좁은 골목을 어깨 너머로 보는 구도인데, 실제 카메라는 11m 뒤, 아래로 약 56도에서 내려다봐요. 그래서 화면 대부분이 땅이에요.
가까이 가면 "Pick up Saw Blade" 안내가 뜨고, E를 누르면 주인공이 몸을 숙여 줍고 아래 칸에 톱날이 들어와요.
작업대 크래프팅

크래프팅 창은 목표 그림과 가장 비슷하게 나온 부분이에요. 빨간 네모 친 두 창을 나란히 보면 바로 보여요. 제목, 한 줄 설명, 무기 그림, 공격력·속도·사거리 막대, 필요한 부품 칸, 제작 버튼까지 배치가 거의 같아요. 다만 목표 그림에서는 벽 가득 공구가 걸린 작업장 안이었는데, 실제로는 평평한 바닥에 작업대 하나와 전등, 드럼통 불이 놓여 있어요.
작업대 근처에서 E를 누르면 다음 단계 레시피 하나만 보여 줘요. 매번 새 부품 하나와 고철을 써요. 톱날과 고철 5개, 작은 모터와 고철 10개, 배터리와 고철 20개, 산업용 모터와 고철 35개예요. 배터리는 밤이 시작될 때, 산업용 모터는 그 90초 뒤에 폐차장에 떨어져요.
무기 5단계

단계가 오르면 숫자만 바뀌는 게 아니라 실제 3D 부품이 파이프에 붙어요. Rusty Pipe에서 시작해 Saw Pole(톱날), Spinning Saw(작은 모터, 톱날이 돌아요), Electro Saw(배터리, 주변 적에게 전기가 튀어요), Overcharged Ripper(산업용 모터)까지 가요. 제작 창 설명도 단계마다 달라서, Saw Pole은 "Crude, but it bites.", 마지막 무기는 "There is no off switch anymore."예요.
부품 모델은 그림에서 뽑은 거라 크기와 방향이 제각각이어서, 불러올 때 모델의 가장 긴 축을 파이프 방향에 맞추고 크기를 정해진 값으로 맞춰요. 파이프 자체는 생성된 모델을 쓰지 않고 코드로 원기둥과 테이프 감긴 손잡이를 만들었어요. 산업용 모터는 3D 변환에 끝내 실패해서 작은 모터 모델을 키워서 대신 써요. 가까이서 보면 마지막 두 단계는 모양 차이가 크지 않아요.
전투: 좀비와 로봇 개

적은 두 종류예요. 고철 좀비는 체력 110에 초속 2.3m로 느리게 걸어오고, 로봇 개는 체력 70에 초속 5.4m로 달려들어요. 폐차 사이를 돌아오도록 길 찾기는 경기장을 1m 칸으로 나눈 흐름장으로 했어요. 왼쪽 클릭은 세 번까지 이어지는 가벼운 공격, 오른쪽 클릭은 스태미나를 쓰는 무거운 공격, Space는 구르기예요.

로봇 개는 처음에 달려들면 주인공 몸 안으로 파고들었어요. 둘 사이가 몸 반지름 합보다 가까우면 밖으로 살짝 밀어내게 고쳤는데, 지금 화면에서도 거의 붙어 있어요.

맞으면 게임 전체가 아주 잠깐 멈추는 히트스톱(가벼운 공격 0.045초, 무거운 공격 0.07초), 화면 흔들림, 데미지 숫자, 불꽃과 파편이 한꺼번에 나와요. 타격감은 확실히 있는데, 여럿을 한 번에 치면 화면 가운데가 하얗게 번져서 무슨 일이 일어났는지 잘 안 보여요. 빨간 동그라미 친 가운데가 딱 그래요. 적을 잡으면 고철이 떨어지고 가까이 가면 저절로 빨려 들어와요.
밤 웨이브와 조명탑

시계는 실제 1초에 게임 시간 1/40시간씩 흘러서, 시작하고 약 2분 20초 뒤 19시에 밤이 와요. 음악이 바뀌고 "NIGHT 1" 제목이 뜨고 웨이브 막대가 생겨요. 웨이브는 데이터로 적어 뒀어요.
export const NIGHT_1: WaveDef[] = [
{ scale: 1.0, groups: [{ kind: "shambler", count: 4, delay: 0 }, { kind: "hound", count: 1, delay: 10 }] },
{ scale: 1.1, groups: [{ kind: "shambler", count: 5, delay: 0 }, { kind: "hound", count: 2, delay: 6 }, { kind: "shambler", count: 3, delay: 16 }] },
// 세 번째 웨이브: 로봇 개 5, 좀비 10
];

밤 조명은 가장 오래 붙잡고 있던 부분이에요. 조명탑 네 개, 작업등, 드럼통 불, 타격 섬광, 무기 불빛을 모두 켜자 WebGPU에서 셰이더 하나가 쓸 수 있는 버퍼 개수를 넘어서 화면이 안 그려졌어요. 재질마다 조명을 4개까지만 받게 하고, 플레이어 가까운 조명 3개만 켜 두는 방식으로 바꿨어요. 조명탑 우선순위를 낮게 잡았을 때는 야드 한가운데가 캄캄해서 한 번 더 올렸어요.
그 결과가 오른쪽 화면이에요. 플레이어 주변은 밝고, 조금만 벗어나면 금방 어두워져요. 목표 그림의 비 젖은 바닥, 불꽃, 간판 불빛 같은 분위기는 없어요.
새벽 승리와 게임 오버

세 웨이브를 다 버티면 "DAWN" 제목이 뜨고, 잠시 뒤 "YOU SURVIVED" 창이 떠요. 죽으면 "YOU DIED"예요. 둘 다 처치 수, 고철, 막은 웨이브, 버틴 시간을 보여 주고, Try Again을 누르면 체력과 무기, 아이템이 처음으로 돌아가요. 사진 속 숫자가 작은 건 제가 시계를 돌리고 웨이브를 건너뛰는 시험용 명령으로 바로 끝까지 가서 찍었기 때문이에요.
이 흐름은 자동 시험으로도 확인해요. 헤드리스 크롬을 WebGPU로 띄워서 게임 시작, 가벼운·무거운 공격, 고철 떨어짐, 작업대에서 두 단계 제작, 19시 웨이브 시작, 새벽 승리, 다시 하기, 사망, 모델 파일 확인, 오류 없음까지 11가지를 봐요. 새벽 1시 44분과 5시 30분에 모두 통과했어요.
해 보니

좋았던 점부터요. 하룻밤 사이에 메뉴부터 탐색, 줍기, 제작, 밤 웨이브, 승리와 사망까지 한 판이 끝까지 이어지는 게임이 나왔어요. 무기에 부품이 실제로 붙는 게 보이는 건 만들어 놓고 봐도 재미있고, 크래프팅 창은 목표 그림을 꽤 잘 따라갔어요. 화면 구석의 성능 표시로는 WebGPU에서 초당 60프레임 근처가 나와요.
아쉬운 점이 더 커요. 목표 그림 옆에 놓으면 차이가 확 보여요. 목표는 폐차가 벽처럼 쌓인 해 질 녘 골목인데, 결과는 위에서 내려다보는 평평한 흙바닥에 폐차와 소품이 드문드문 놓인 모습이에요. 위 사진처럼 한가운데는 거의 빈 땅이에요. 빨간 동그라미 안의 작은 사람이 주인공이에요. 카메라가 높아서 캐릭터도 작고, 밤에는 조명 원 밖이 금방 캄캄해요. "작동하는 데모가 목표가 아니다"라고 적어 보냈지만, 아침에 남은 건 잘 작동하는 데모였어요.
지금 상태와 남은 것
- 폐차장 1구역, 적 2종, 무기 5단계, 밤 웨이브 3번, 새벽 승리와 사망, 다시 하기까지 한 판이 돌아가요.
- 3D 에셋은 31개 중 26개가 생성됐고, 실패한 것은 비슷한 모델로 대신해요. 로봇 개는 코드로 만든 모델을 써요. 자세한 과정은 2편에 있어요.
- 두 번째 구역과 보스는 시작하지 않았어요. Steam 연동도 자리만 있고, 저장과 업적은 지금 브라우저에 저장해요.
- 그날 새벽 6시 17분 이후로 손대지 않았어요.
그날 밤 빌드를 그대로 글 아래에 올려 뒀어요. 직접 해 보고 어땠는지 댓글로 알려 주세요.
댓글 0
아직 댓글이 없어요. 첫 이야기를 남겨 주세요.