게임 프로젝트 · USC Games · That Game Jam · 5인 팀

이 몸 바람처럼 (Light as Wind)

바다를 건너 머나먼 하늘을 향해 떠나는 몽환적인 픽셀 아트 횡스크롤 게임입니다. 저는 팀의 디자이너이자 엔지니어로서 10개 레벨 중 3개의 레벨 디자인을 했고, 게임을 떠받치는 물리·셰이더·파괴 시스템 여러 개를 만들었습니다.

레벨 03 게임플레이: 아귀를 피해 숨는 장면. 게임 속 모든 생물은 스켈레탈 리그 없이 절차적으로 애니메이션됩니다.

나의 역할

디자이너 · 엔지니어

레벨 04, 06, 10의 레벨 디자인(배경, 동선, 메커니즘)을 했습니다. 게임 전반에 걸쳐서는 인터랙션 메커니즘을 디자인하고, 게임플레이 로직과 이펙트를 구현했으며, QA와 버그 수정을 맡았습니다.

엔지니어링에서는 움직이는 것들의 손맛에 집중했습니다. 바람에 날리는 종이, 황새치의 수영, 게의 덩굴 스윙, 부서지는 소품 등이 그 예입니다. 게임의 ‘공기 벽’ 셰이더도 직접 작성했습니다.

이 프로젝트에는 엄격한 규칙이 있습니다. 모든 시스템의 로직은 엔진 타입 없이 순수 C#으로 작성해 나중에 Unity 밖으로 옮길 수 있게 하고, 모든 변경은 스크린샷보다 먼저 프로브, 로그, 경로 봇 같은 데이터로 검증합니다.

엔진
Unity 6 / C# / HLSL
팀
학생 5명, USC Games
플랫폼
Windows (itch.io)
상태
파트 I 출시

프로젝트의 기반

렌더링 & 절차적 애니메이션

이 몸 바람처럼은 두 가지 기술적 기반 위에 만들어졌습니다. 움직이는 3D 원근 카메라에서도 무너지지 않는 픽셀 아트, 그리고 스켈레탈 리그 하나 없이 코드만으로 움직이는 생물 애니메이션입니다. 제가 만든 시스템들은 이 기반 위에서 동작합니다.

01

커스텀 렌더 파이프라인

게임은 단계적으로 URP를 떠나 자체 파이프라인으로 옮겨 갔습니다. 이 파이프라인은 순수 C#으로 작성한 엔진 독립적인 프레임 그래프 위에 세워졌고, Unity는 여러 백엔드 중 하나일 뿐입니다. 각 단계는 레퍼런스 프레임과 텍셀 단위로 대조해 검증했습니다. 셰이더 변형은 603개에서 36개로 줄었고, 한 프레임 전체의 GPU 비용은 약 0.4–0.5 ms입니다.

02

원근 속의 픽셀 아트

각 오브젝트는 저해상도 텍셀 격자에 강체 단위로 스냅되고, 남은 서브픽셀 오프셋은 G-buffer에 저장했다가 화면 해상도에서 해석합니다. 덕분에 카메라가 미끄러지듯 움직여도 실루엣이 일렁이지 않습니다. 부드러운 반사광은 월드에 고정된 프로브를 쓰는 2.5D Radiance Cascades로 만들며, 비용은 약 0.3 ms입니다.

03

절차적 애니메이션

스켈레탈 리그는 어디에도 없습니다. 진행파로 움직이는 물고기 척추, XPBD와 Verlet 체인, 컴퓨트 셰이더로 시뮬레이션하는 해파리, 그리고 단 한 번의 드로우 콜로 그려지는 5,000마리 이상의 Boids 물고기 떼가 있습니다.

레벨 디자인

제가 디자인한 레벨

시스템

물리, 셰이더 & 파괴

주요 작업 05

01 · 시뮬레이션

바람에 날리는 종이

각 종이는 바람이 불어 가는 쪽 모서리를 경첩 삼아 회전하며 들리고, 34°까지 벗겨진 뒤 떨어져 나갑니다. 공중에서는 속도가 지수적 추종으로 목표 바람 속도에 다가가고, 낙엽처럼 흔들리는 움직임(±0.3 m, 주기 2.1 s)이 기울기와 흔들림을 연동해 방향을 틀 때마다 종이가 그쪽으로 기울어집니다.

바람이 닿기 전에는 부족 감쇠 스프링으로 모서리가 팔랑입니다. 벽 제약이 포스터를 벽 앞에 붙잡아 두고 벽면을 따라 미끄러져 떨어지게 하므로, 벽을 뚫고 지나가는 일이 없습니다.

돌풍 1회당
종이 15–17장, 0.22–2.33 s 안에 모두 화면 밖으로
벽 관통
0.7–2.6 m → 0
모델은 순수 C#(System.Numerics, 엔진 타입 없음)으로 작성되었고, Unity는 그리기만 담당합니다.

02 · 셰이더 · Worley 노이즈

공기 벽: 꿈속 바다의 피부

보이지 않는 벽이 버그가 아니라 꿈의 일부로 읽혀야 했습니다. 벽에는 천천히 흐르는 Voronoi / Worley 그물이 나타납니다. 선은 셀 경계까지의 실제 거리로 그려지기 때문에 어떤 각도에서도 1픽셀 두께로 끊김 없이 유지되고, 경계마다 플랑크톤 색 중 하나가 입혀지며, 반짝이는 금빛 입자가 몇 개 떠다닙니다.

부딪히면 한 쌍의 고리가 퍼져 나가며 그물을 밀어내고, 충돌 지점에서 거품이 피어오릅니다. 이 막은 가까이 다가갈 때만 나타납니다(1.8 m에서 시작, 0.95 m에서 완전히 표시). 밝기는 디더링 없이 깔끔한 단계로 나뉘며, 프로젝트 자체 헤더 위에서 이식 가능한 HLSL로 작성했습니다.

03 · 게임 필

황새치의 수영

황새치는 참치형 척추 파동으로 헤엄칩니다. 질량 가중 반동 덕분에 실제 물고기처럼 머리가 꼬리와 반대로 흔들리고, 꼬리를 치는 주파수는 스트로할 수로 정해집니다.

조작감도 다듬었습니다. 실제로 벽에 닿기 전에는 감속하지 않고(거리는 주둥이 끝에서 진행 방향으로 측정), 지붕과 풀이 덮인 비탈을 따라 속도 손실 없이 미끄러지며, 도약 사이에 잠수하고, 위아래 방향 전환이 더 빨라졌습니다.

04 · 시뮬레이션

게의 덩굴 스윙

게가 진자이고, 덩굴은 게의 집게를 따라갈 뿐입니다. 2.5D 게임에서는 순수 3D 거리로 판정하면 자꾸 잡기에 실패해서, 잡기 판정은 화면 평면에서 측정합니다. 플레이어는 스윙과 위상이 맞을 때만 반동을 줄 수 있고, 에너지 상한(최대 72°)이 긴 덩굴에서 게가 화면 밖으로 튕겨 나가지 않도록 막습니다.

각 덩굴은 노드 18개짜리 Verlet 로프로, 제약 패스 8회, 물의 저항, 느린 흔들림을 갖습니다. 집게 아래의 노드는 게의 등딱지 밖으로 밀어내 절대 파고들지 않게 했습니다.

평균 프레임, 레벨 7/8/9
6.4/7.7/8.5 → 1.7/2.6/2.7 ms
16.7 ms 초과 프레임
89/165/166 → 4/0/0

05 · 파괴

레벨을 조각내기

이 게임에는 임포트한 메시가 하나도 없기 때문에, 파괴란 곧 생성된 지오메트리를 자르는 일입니다. 레벨 06의 무너지는 터널에서는 동굴 천장이 스스로 부서집니다. 정점을 용접한 뒤 union-find로 닫힌 바위 단위로 묶고, 긴 바위는 무작위 평면으로 클리핑하며(Sutherland–Hodgman, 모든 속성 보간), 잘린 면마다 팬으로 뚜껑을 씌워 모든 파편이 닫힌 솔리드로 유지되게 합니다.

절단은 프레임당 4 ms 예산의 코루틴으로 실행되며, 플레이어가 아직 60 m 떨어져 있을 때 시작합니다. 140–220 프레임에 걸쳐 바위 610개가 파편 169개가 됩니다. 작은 소품은 이웃끼리 이음매를 공유하는 사전 분할 조각으로 부서지고, 파편은 물리 엔진을 아예 거치지 않아 프레임당 약 0.013 ms밖에 들지 않습니다.

터널 붕괴
바위 610개 → 파편 169개
소품 파괴 최악 프레임
14.6 → 3.3 ms