이름 짓는 약속을 지키지 않은 댓가
아이소매트릭 뷰에서 거대보스의 문제를 처음으로 깊이 생각할 계기가 된 프로젝트에서 한번은 사장님의 요청으로 던전을 무작위로 생성하는 요구사항이 등장했습니다. 사실 당시 개발하던 그 게임이 나름 경쟁작으로 생각하던 세계적인 프랜차이즈 게임에서는 이미 던전을 조건에 따라 랜덤으로 생성하고 있었고 이게 제법 잘 동작했기 때문에 던전을 한 땀 한 땀 정성 들여 만들고 있던 우리들에 비해 반복되는 컨텐츠에 대해서는 높은 생산성을 가질 수 있어 보였습니다.
당시 우리들은 이미 성장 구간에 등장하는 여러 던전을 정성 들여 만들어 꽤 인상적인 경험을 주는 던전들이 있었지만 엔드컨텐츠마저도 이런 방식으로 만들기는 어려울 거라고 예상하고 있었습니다. 현대의 엔드컨텐츠는 비용 대비 효율이 높은 메커닉에 바탕을 두고 제작하고 있지만 이 시대까지는 아직 MMO 게임의 엔드컨텐츠를 분기 단위의 대규모 업데이트를 통한 수직 성장 요소로 대신하던 시대였고 이 방식이 얼마나 비싸고 고통스러운지 우리들 스스로도 잘 알고 있었습니다. 그래서 사장님의 던전을 무작위로 생성할 수 있게 만들자는 의견은 별다른 반대 의견을 만나지 않고 팀 깊숙한 곳까지 한 번에 도착했습니다.
우리들 중에 3D 게임에서 이런 기능을 개발해본 사람은 없었고 사장님의 특별 요구사항인 만큼 다음 보고 전까지 그럴듯한 진척을 만들어야만 했으며 그 보고 시점은 그리 멀지 않은 상황이었습니다. 기술 부서에서는 기술적으로 무작위 생성된 던전을 어떻게 서버와 클라이언트가 서로 주고 받은 다음 동기화하고 여러 플레이어들에게 같은 상황을 경험하게 할 지, 또 레벨의 테마, 길이, 난이도, 등장할 몬스터 따위를 어떻게 설정하게 할 지 대략 고민하기 시작했고 기획에서는 무작위로 생성할 던전을 크게 던전 배경, 그 안에 등장할 적, 자동화된 기믹 등으로 구분해 요구사항을 만들기 시작합니다.
실은 어디서부터 시작해야 할 지 전혀 갈피를 잡을 수 없어 자료를 찾다가 Skyrim’s Modular Approach to Level Design이라는 스카이림의 사례를 찾았고 비슷한 시점에 스팀을 통해 이 분들이 사용한 인하우스 도구를 직접 만져봤습니다. 정리하면 던전의 테마에 따른 던전의 주요 형태를 정의하고 이 형태를 규격화한 다음 각각의 구성요소를 규격에 맞춰 블록 모양으로 만들어 이들을 조합해 던전 모양을 구성하고 이 위에 몬스터와 기믹을 배치해 완성하는 것이었습니다.
스카이림은 던전을 무작위로 생성하지는 않았지만 던전을 무작위로 생성하기 위해 어디서부터 시작해야 할 지 힌트를 얻기에는 충분했습니다. 특히 스위치로 열리는 문 같은 퍼즐은 아무리 단순한 모양이라 하더라도 레벨디자이너들에게 배포하기 쉽지 않았는데 스카이림에서는 창고라는 레벨 안에 흔한 퍼즐 메커닉을 만들어 배치해 놓고 이들 중 하나를 골라 복사한 다음 만들던 레벨에 붙여 넣고 메커닉의 구성요소를 던전 곳곳에 배치해 완성하는 방식을 사용했는데 이 방식은 우리들이 겪던 메커닉 배포의 어려움을 꽤 많이 해결해 주었습니다.
결국 온전히 동작하는 무작위 던전 생성 시스템을 개발했는데 당시 우리들은 던전 레벨에 집중해 무작위 모양의 던전이 만들어졌지만 그 안에서 나타날 몬스터들을 무작위로 배치하는 작업은 별로 성공적이지 못했습니다. 몬스터들이 나타나기는 했지만 레벨디자이너가 의도를 가지고 하나하나 배치한 몬스터들을 상대하던 우리들은 규격에 맞춰 투박하게 등장하는 몬스터들은 그냥 마주쳐 두어 대 때려 보기만 해도 이 조합이 의도를 가진 조합인지 그렇지 않은지 바로 알 수 있었습니다. 그래서 팀에서는 사장님의 요구에 따라 무작위 조합되는 던전 시스템을 개발했지만 과연 우리가 개발한 시스템이 동작하기는 하지만 게임으로써 재미있는 경험을 고객에게 줄 수 있기는 한 것인지 고민에 빠집니다.
사실 이 시점에서 시간을 더 투입해 경험을 개선할 방법을 찾았더라면 해피엔딩으로 끝날 수도 있었겠지만 일단 기능이 완성되었고 이 기능에 맞춰 에셋을 생산했으며 여러 테마에 따른 레벨을 플레이 시간, 길이, 난이도 등에 따라 생성할 수 있게 됐으니 사장님께 드리는 보고에는 기능이 완성되었다고 보고했고 담당자들은 다른 엔드컨텐츠를 개발하는 업무로 넘어갔습니다. 그리고 이 기능이 어떻게 되었을지는 굳이 설명하지 않아도 될 거라고 생각합니다.
한편 이 기능을 개발하기 위해 참고한 스카이림 모듈러 레벨디자인 문서에는 한 가지 레벨 테마를 구성하는 각 모듈의 하위 구성요소들의 네이밍 규칙의 중요성을 강조하고 있습니다. 네이밍 규칙은 한 번 정의해 놓고 시간이 지난 다음 규칙을 재 정의하려고 하면 이미 이 규칙에 맞춰 만들어진 수많은 에셋을 수정해야 하므로 규격 재 정의에 비용이 아주 높습니다. 단순히 파일 이름을 바꾸는 정도로 끝나지 않습니다. 현대에는 언리얼 에디터 안에서 파일 이름을 바꾸면 파일을 가리키는 다른 에셋을 찾아 함께 수정해 연결을 끊지 않고 이름을 바꿀 수 있기는 하지만 이름을 바꾼 그 파일이 에디터 내부에서 생성된 것이 아니라 에디터 바깥으로부터 임포트 된 파일이라면 에디터 바깥에 있는 파일을 함께 수동으로 수정해 줘야만 합니다. 자동으로 바뀌는 부분과 그렇지 않은 부분이 둘 다 있어 일이 상당히 복잡합니다.
하지만 미래에도 잘 바뀌지 않을 단단한 이름 규칙을 만들기는 상당히 어렵습니다. ✈️ The Maddening Mess of Airport Codes! ✈️라는 유튜브 영상을 보면 미래에도 잘 동작할 이름 체계를 만드는 일이 얼마나 어려운 일이고 또 한번 잘못 만들어진 체계가 미래에 어떤 댓가를 치르게 만드는지, 또 절대 바뀌지 않으리라 생각한 조건이 미래에 얼마나 쉽게 바뀔 수 있는지 알 수 있습니다. 영상의 모든 부분이 가슴을 답답하게 만들지만 개인적으로 영상을 보다 말고 ‘하… ㅅㅂ…’ 이라고 말하게 만든 부분은 분명 공항 코드는 공항 하나에 코드 하나를 부여할 거라는 조건은 절대 바뀌지 않을 거라고 가정하고 만들어졌는데 두 나라의 국경에 각 국가가 각각 건설한 두 공항이 서로 연결되어 사람들이 한 공항으로 인지하지만 실은 두 공항이고 코드도 두 개 발급 되어 있을 뿐 아니라 공항에 연결된 열차에 해당하는 코드에 이르기까지 기존의 이름 규칙 입장에서 아주 도전적인 사례를 설명하는 것이었습니다.
하지만 이런 일이 생길 수 있음을 이해합니다. 내 지능과 한 번 만들어 끝까지 가는 정책에서 미래의 요구사항에도 단단히 동작하는 규칙과 정책을 정의하고 싶습니다. 하지만 우리는 이번 주 로또 번호조차 예상하지 못하는 입장이고 미래에 일어날 일을 미리 예측해 그 일까지 포용하는 규칙을 만들어내기는 거의 불가능합니다. 하지만 그럼에도 현재 시점에 존재하는 규칙은 반드시 지켜야 하는데 프로젝트 규모가 작을 때는 별 문제가 생기지 않을 수 있지만 규모가 커질 때 순식간에 문제가 생깁니다.
특히 아트 에셋은 여러 에셋이 모여야 한 가지 기능으로 동작해 서로가 필요합니다. 어떤 에셋을 어떻게 사용할 목적으로 만들었는지 에셋 생산 직후 바로바로 데이터화 하지 않으면 시간이 조금만 지나도 이 메시는 도대체 어디다 쓰라고 만든 것인지 전혀 알 수 없게 됩니다. 가령 특정 클래스 캐릭터가 입을 바지 에셋이 있다고 합시다. 그런데 이 바지 에셋은 대강 머테리얼인스턴스, 텍스처, 스켈레탈메시, 피직스 에셋이 필요하고 인게임에서 아이템 모양으로 사용할 경우에 대비해 아이콘으로 사용할 스프라이트 에셋도 필요합니다. 그런데 만약 이들이 각기 다른 작업자로부터, 각기 다른 시점에 생산되는데 서로 파일 네이밍 규칙이 다르다면 서로를 찾을 방법이 없어 정말 큰일 납니다.
크게 두 가지 관리 스타일이 있는 것 같습니다. 하나는 네이밍을 칼같이 맞춰 처음 보는 스켈레탈메시도 같은 이름으로 검색하면 이 에셋과 연관된 스프라이트 에셋을 검색해 아이콘을 찾아낼 수 있도록 하는 것, 다른 하나는 게임에 등장할 에셋 집합마다 필수 에셋 구성요소를 데이터 모양으로 정의하고 구성요소에 해당하는 모든 에셋을 지정하지 않으면 등록할 수 없도록 하는 것입니다. 전자는 의지를 가진 개인이나 그룹이 철저하게 통제하지 않으면 잘 지켜지지 않으며 후자는 등록하기 귀찮으니까 아무 에셋이나 적용해 잘 지켜지지 않습니다. 둘을 비교하면 그나마 후자가 문제가 생길 때 상황 추적과 수정이 상대적으로 쉬운 편입니다.
네이밍의 중요성을 본격적으로 생각하기 시작한 에피소드와 미래의 요구사항 변화에도 단단하게 동작하는 네이밍 규칙을 만들기 어렵다는 이야기를 하다가 갑자기 현재에 그런 불완전한 네이밍 규칙이라도 똑바로 잘 지켜야 하며 이를 위한 두 가지 접근이 있다는 이야기를 하는 이유는 오늘 네이밍 규칙이 일치하지 않는 스켈레탈메시와 아이콘용 스프라이트 에셋 400세트를 받았고 이걸 이번 주 안에 다 찾아서 연결한 데이터를 만들어야 하는 상황이기 때문입니다. 사실 다른 프로젝트였으면 이 상태를 보고 그래도 작업을 말까 고민하기에 앞서 도대체 어쩌라는 거냐고 분노할 수도 있었겠지만 할까 우리가 처한 상황을 고려해 이번에는 제 선에서 상황을 흡수하기로 했습니다. 하지만 이 빚은 꼭 적립했다가 나중에 우리가 위기에 처할 때 반드시 써 먹을 작정입니다. 아니 하루이틀 해 온 거 아닌 선수들 끼리 이러면 안되죠.
앞서 설명한 두 가지 관리 스타일 중 두 번째가 잘 동작하지 않는 이유 중 하나는 이상할 정도로 인게임에 정확히 사용되지 않을 에셋 생산에 거부감이 큰 경우가 있어서이기도 합니다. 가령 문은 보통 열리기도 하고 또 닫히기도 하지만 당장 열리기만 할 계획이라면 정말 열리는 애니메이션만 딱 맞춰 제작 요청 해야 할 때가 있습니다. 이런 상황에서 필요할지 아닐지 모르는 아이콘용 스프라이트 에셋을 포함하는 에셋 세트를 만들어야만 등록할 수 있는 시스템은 반감을 일으킬 수 있습니다. 하지만 나중에 똑같은 문을 닫고 싶으면 그때 가서 다시 정식 제작 요청 프로세스를 통해 똑같은 문의 닫히는 애니메이션을 요청해야만 하는 일이 생기기도 합니다.
결론. 프로젝트 규모가 커지면 네이밍 규칙이 굉장히 중요해집니다. 네이밍 규칙에 따라 서로 함께 사용해야 할 에셋을 쉽게 찾아낼 수 있지만 네이밍 규칙을 지키지 않으면 연관된 에셋을 찾아내기 아주 어려워집니다. 이런 상황에 대응하는 두 가지 접근 방법이 있는데 하나는 네이밍 규칙을 칼 같이 맞추는 것, 다른 하나는 함께 사용될 에셋들을 모은 한 세트 단위로 데이터를 만들 수 있기 전에는 에셋을 시스템에 등록할 수 없게 하는 것입니다. 양쪽 모두 장단이 있고 양쪽 모두 규칙을 잘 동작하게 만들기 위해 조금 다른 방식으로 접근해야 합니다. 어떤 방식이든 네이밍 규칙을 지키지 않으면 누군가 지독한 삽질을 해야 하며 이번 주에는 그게 바로 접니다.