[아카이브] 울티마 온라인의 리소스 시스템

Zerasion
By Zerasion in Blue Board,
sequoia 님이 작성하셨던 포스팅의 아카이빙입니다. ---   이 글에서 스레드 분리되었습니다.
파파랑님의 주변 친구 2 입니다. :-) 라프 코스터의 해당 포스팅은 제가 번역했던 게 있는데, 워낙 영어 실력이 짧은데다 대충 아는 사람끼리 공유하느라 음슴체로 번역해놔서 그대로 올리기는 좀 민망하네요. 일단 어투를 바꾸고 좀 곁가지로 샌 부분 쳐내면서 의역을 해봤습니다. 줄인다고 줄였는데도 내용이 꽤 기네요. "시뮬레이션의 꿈"의 주제의식과 라프 코스터의 지향점은 좀 다른 것 같은데, 일단 아래 글도 라프코스터가 2006년에 올린 글이니까 감안해서 보시면 될 것 같습니다.
0. (시뮬레이션의 꿈 아티클에 달린 라프 코스터의 댓글에서)
울온이 구체적인 예로 들어진 김에 말하자면, 울온은 내부에선 엄청 심플하게 만들려고 노력했고 실제로 그 시뮬레이션은 매우 심플합니다. 물론 액터 숫자만으로도 복잡성의 함정에 빠지게 되었지만, 관련해서 아래와 같은 글을 썼습니다. (이게 이번에 번역한 글) 그 중 마지막 파트가 정확히 이 글(시뮬레이션의 꿈)에서 말하는 문제에 대한 것입니다. http://www.raphkoster.com/2006/06/03/uos-resource-system/
http://www.raphkoster.com/2006/06/04/uos-resource-system-part-2/
http://www.raphkoster.com/2006/06/05/uos-resource-system-part-3/ 그러나 울온에서 위 시스템에 기반해서 만든 것 중 많은 성공적인 요소가 완전히 아포페니아 디자인에 대한 것입니다. 이에 대해서도 글을 썼습니다. http://www.raphkoster.com/2006/06/09/why-dont-our-npcs (이건 번역하지 않았습니다.)
1.
라프 코스터는 리소스 시스템 디자인과 함께 "드래곤 시나리오"를 오리진 입사 지원서에 첨부했는데, 그 시스템 디자인이 울온의 핵심 메카닉으로 채택되면서 오리진에 입사할 수 있게 되었습니다. 드래곤 시나리오는 시뮬레이션의 꿈에도 인용된 그 내용이죠. 원래의 게임 메카닉대로라면 위 상황을 타개하기 위해 플레이어들은 드래곤을 죽이거나 드래곤에게 먹이를 바치는 방법으로 마을을 지킬 수 있었어야 합니다. 그러나 당시(1995년) 기술로는 드래곤이 먹이를 찾기 위해 주변 탐색을 할 수 있는 범위가 한 화면 정도에 불과했고 그나마도 너무 느렸기 때문에 실제로 현실화되지 못했죠. 2.
위와 같은 시스템을 만들기 위한 아이디어는 기존 MUD의 제작 시스템을 개선하기 위한 아이디어에서 출발했습니다. 원래 전통적인 MUD에서는 아이템이 "마스터 카피"의 ID를 갖고 있고 마스터 카피의 특성을 이용해서 생성되는 방식이었고, 제작 시스템은 레시피 시스템으로 되어있었습니다. 그런데 레시피 시스템은 기본적으로 테이블을 관리하는 방식이고 나무 재료를 추가할 때 마다 나무와 관련된 테이블 전체를 엎어야 하는 시스템이었습니다. 새로운 아이디어의 핵심은 오브젝트에 추상화된 속성을 넣어 오브젝트가 "나무로 만들어졌음"을 추적할 수 있게 만들고 레시피는 재료 오브젝트에 "나무로 만들어졌는지"를 확인하게 만드는 방식이었습니다. 즉 아이템이 어떤 재료로 사용될 수 있는지를 리소스의 집합으로 표현한 것이죠. (이 때까지는 리소스가 "라벨"일 뿐이었지만 나중에 swg에서는 스탯 있는 리소스 개념을 추가했습니다.) 울온 코어 팀의 노력으로 리소스 시스템이 발전하게 되었습니다. 울온에서 대부분의 오브젝트는 4가지 타입의 리소스의 "라벨"을 갖고 있습니다. (울온에서의 오브젝트는 아이템, 자연물, 인공물, NPC, 플레이어를 모두 포괄합니다.) PRODUCTION :
오브젝트의 "재질"을 의미합니다. 자연물이라면 이 타입의 리소스를 계속 생산해내기 때문에 regrowth rate가 있고, 인공물이라면 regrowth rate는 없고 재질만을 나타내겠죠. 이 리소스 타입은 모든 오브젝트에 붙어있고, 나머지 리소스 타입은 AI와 관련이 있습니다. FOOD :
오브젝트가 먹는 음식을 의미합니다. 오브젝트는 FOOD타입의 오브젝트를 근처에서 찾고, 찾아가서 먹습니다. 이 리소스 타입에는 bite size(입 크기)와 stomach size(배 크기), 그리고 최소 관심 크기가 있어서 한 번에 bite size씩 먹고 stomach size가 찰 때 까지 먹는데, 최소 관심 크기 이하를 PRODUCTION하는 오브젝트는 관심을 갖지 않고 지나칩니다. SHELTER :
오브젝트가 집으로 삼는 타입의 리소스입니다. 오브젝트는 SHELTER 타입의 오브젝트를 근처에서 찾고, 적당한 크기(이 값도 정의되어 있겠죠?)라면 둥지(lair)로 삼습니다. 배가 부르면 둥지로 돌아옵니다. DESIRE :
오브젝트가 좋아하는 리소스입니다. 배도 부르고 둥지도 마련했다면 이 타입의 리소스를 찾아다닙니다. 찾으면 둥지로 가져옵니다. 가져올 수 없다면 둥지로 돌아가는 대신 이 리소스 근처를 배회합니다. aversion 플래그를 켜면 좋아하는 대신 무서워하거나 피합니다. 마슬로우의 욕구 단계 이론처럼 오브젝트는 FOOD->SHELTER->DESIRE 순으로 만족하려고 합니다.
예를 들어 토끼 오브젝트는 다음과 같습니다.
PRODUCTION : FUR(약간, 리젠 안됨), MEAT
FOOD : GRASS, FLOWER, VEGETABLE (매우 작은 입 크기, 작은 배 크기)
SHELTER : GRASS, BUSH (BUSH를 둥지로 삼음)
DESIRE : aversion CARNIVOREMEAT 늑대 오브젝트는 다음과 같습니다.
PRODUCTION : FUR(중간 양, 리젠 안됨), CARNIVOREMEAT
FOOD : MEAT (중간 입 크기, 작은 배 크기)
SHELTER : TREE, CAVE (CAVE를 둥지로 삼음)
DESIRE : aversion CARNIVOREMEAT 늑대 같은 경우 무리짓기 AI가 있어서 서로 가까이 있고 싶어하고 무리의 입 크기/배 크기를 더합니다. 위의 드래곤은 다음과 같이 됩니다.
PRODUCTION : SCALE(중간 양, 리젠 안됨), CARNIVOREMEAT(매우 많은 양)
EAT : MEAT, CARNIVOREMEAT (큰 입 크기, 매우 큰 배 크기)
SHELTER : MOUNTAIN, CAVE (CAVE를 둥지로 삼음)
DESIRE : GOLD, GEM, MAGIC
3.
월드에서도 리소스가 생산되는데, 모든 걸 오브젝트로 만들기엔 서버 용량이 무리가 있어서 8x8 청크마다 청크 알(chunk egg)라는 보이지 않는 오브젝트를 만들었습니다. 청크 알은 청크의 static 지형 데이터를 분석해서 해당 청크에서 어떤 리소스를 생산할 지 판단합니다. 나무가 있으면 WOOD를 생산하고, 광맥이 있으면 ORE를 생산하는 식으로 작동하는데, 유저 눈에 보이는 건 static 데이터이기 때문에 유저가 보기엔 나무 하나만 베면 8x8지역의 나무가 다 빨려나오는 걸로 보이는 부작용(?)이 있습니다. 그래서 숫자가 적은 오브젝트는 그냥 다이나믹 오브젝트로 배치하고 다이나믹 오브젝트는 직접 리소스를 생산하기도 하지만 오브젝트에 스크립트를 코딩해서 붙일 수도 있었습니다. 당연히 라이브 단계에서는 버그의 온상이 되었고(...) 라프코스터가 울온에서 손 뗀 뒤로는 더욱 버그의 온상이.... 주제와는 관계없는 얘긴데 어떤 사람이 "날" 스크립트에다가 플레이어 시체도 자를 수 있는 코드를 넣었다가 인육 먹는 게임이 된 적도 있다고 합니다. 오브젝트가 스폰될 때는 PRODUCTION에 있는 리소스를 월드에 좀 가져오는 셈인데, 전역적인 리소스 은행을 두고 월드 전체에 퍼진 리소스의 양을 제한했습니다. 즉 월드에서 특정 리소스가 파괴될 때 리소스 은행으로 가져오고, 스폰될 때 리소스 은행에서 리소스를 내주는 방식이죠. 리소스 은행에 고기가 없다면 스폰될 때 고기가 필요한 토끼 같은 동물이 더이상 스폰되지 않습니다. 이걸 "닫힌 경제"라고 부릅니다. 오브젝트 스폰은 자연발생설을 따라(...) 잔디가 많은 곳에서는 잔디 먹는 오브젝트가 생성되고 고기가 많은 곳에는 고기 먹는 오브젝트가 생성되는 식이었는데, "스폰 영역"을 지정해서 영역마다 예를 들면 잔디 먹는 오브젝트가 필요할 때 이 영역에는 토끼를, 저 영역에는 사슴을 스폰하는 식으로 지정할 수 있었습니다. 위에서도 말했듯 늑대는 무리짓기 AI가 있었는데, 혼자 있을 때는 자기 입 크기보다 큰 고기를 생산하는 사슴을 공격하지 않는데, 무리를 지으면 입 크기를 더하기 때문에 늑대 무리는 사슴을 공격하게 되었습니다. 사슴이 없으면, 사람도 공격합니다. 근데 이렇게 배고플때만 공격하게 만드니까 늑대가 항상 위협적인 건 아니었는데, 게임플레이 상 어떤 동물은 항상 위험하길 바라는 팀원이 있어서 "어그로"시스템을 넣게 되었습니다. 어쨌든 그래서 플레이어가 토끼를 너무 열심히 잡으면 늑대는 먹을 토끼가 없으니 무리를 지어 사슴을 사냥하고, 드래곤은 평소에 먹던 사슴이 너무 적어지니 음식을 찾기 위해 탐색 범위를 넓히다가 탐색 범위가 플레이어 마을까지 넓어지면 마을을 공격하게 되는 거죠. 근데 이 탐색 연산 자체가 너무 비싸서 최적화를 좀 했는데, 일단 탐색을 좀 자주 안 하게 해도 안 되어서 유저가 안 보는 곳에 있는 오브젝트는 잠든 상태로 만들어버렸습니다. 당연히 이렇게 하면 큰 스케일의 월드 시뮬레이션은 망했고...... 그리고 리소스 수요를 제대로 조사를 못 해서 문제가 생겼는데, 유저가 고기는 먹어 없애지만 모피FUR는 인벤에 쌓아뒀기 때문에 모피가 없어서 토끼가 리젠 안 되는 현상이 생겨버렸습니다. 게다가 굳이 이런 거 이렇게 열심히 만들어야 되냐 싶은 생각을 가진 팀원들도 있었는데, 베타 때 구현 책임자가 그런 사람 중 하나라서 결국 알파 때는 좀 된다 싶던 게 베타 때는 하나도 작동하지 않게 되었습니다. (ㅜㅜ)
4.
울온의 마이닝 시스템은 변성transmutation이라는 방식으로 만들어졌습니다. 위에서 말한 청크 에그가 맵의 static데이터를 분석해서 "광맥pile of ore"이라는 오브젝트가 있으면 광물ORE 리소스를 생산했는데, 그 광물의 종류가 철IRON이냐 구리COPPER냐에 따라서 광맥의 렌더링 색깔을 바꿔줘야 했기 때문에 오브젝트에 변수 값을 저장할 수 있는 object variable (objvar)라는 기능을 사용했습니다.  그래서 ORE를 생성하는 청크 에그의 objvar에 금속 타입을 랜덤하게(타입 별로 레어도 차이는 두고) 설정하는 스크립트를 넣고, 렌더링할 때도 금속 타입에 대해 색깔을 룩업하는 테이블을 두어 색깔 차이를 주고, 실제로 플레이어가 채광핬을 때 생성된 ORE 아이템에 청크 에그의 금속 타입 objvar를 전송transfer했습니다. 마찬가지로 ORE를 제련해서 METAL 주괴로 만들 때도 ORE 아이템의 금속 타입 objvar를 주괴 아이템에 전송하고, 실제로 갑옷을 생성할 때도 마찬가지 방법으로 했는데, 두 가지 이상의 타입의 금속으로 아이템을 생성했을 때는 아마도 더 흔한 금속 타입을 받도록 했던 것 같습니다. 나중에 swg에서는 이 방법 대신 IRON 리소스 타입과 COPPER 리소스 타입이 METAL 리소스 타입을 상속받는 방식으로 만들었습니다. 변성을 사용해서 여러 가지 다른 짓(?)도 할 수 있었는데, 돌 마법사는 ORE를 MAGIC으로 바꿀 수 있다든가, 드루이드의 힘은 근처의 GRASS나 TREE의 양에 영향을 받는다든가, 네크로맨서는 누가 죽을 때마다 청크 에그에 DEATH리소스를 축적해놨다가 "mine death magic" 스킬로 퍼갈 수 있게 한다든가 하는 식으로 만들었습니다. 네크로맨서는 이런 식으로 희생용 제단도 만들고 죽음의 사원도 만들고... 이거 말고도 청크 에그에 흔적을 남기게 해서 "진짜 추적"을 만든다든가, MAGIC과 METAL을 합쳐서 MITHRIL을 만들게 한다든가, 드래곤의 불이 진짜 불을 붙게 만든다든가, KARMA나 REPUTATION을 만든다든가, HUMIDITY가 GRASS의 리젠율과 METAL의 녹스는 속도(decay rate)에 영향을 주게 만든다든가 하는 식으로 응용이 가능할 듯 합니다.
5.
그런데 여기에 빠진 게 바로 "인과율"입니다. 드래곤 예시를 보면, 드래곤이 배고파서 온건지 랜덤 스폰으로 온 건지 플레이어가 분간할 수가 없는 거죠. 죽여버리면 편하지만 먹을걸 줘서 해결이 가능한지는 알 방법이 없는 거. 좀 다른 예를 들어서, 농작물을 토끼가 먹어치우면 농부가 토끼를 싫어하게 만들 수는 있는데, 실제로 농부가 플레이어에게 "토끼가 내 농작물을 먹어치우고 있어. 토끼를 죽여줘"라고 말하게 만들고 싶은 거죠. 이 부분은 만들자고 제안했지만 못 만든 건데, 농부는 농작물을 DESIRE하고, 토끼는 농작물을 EAT하기 때문에, 농부에게 "그가 DESIRE하는 자원을 갖고 경쟁하는 상대를 싫어하기"라는 템플릿을 넣어놓을 수 있게 만드는 거죠. 플레이어가 토끼를 죽이면 농부가 보상을 지급하는 걸 정적인 퀘스트를 만들어넣지 않고도 구현할 수 있게 되는 겁니다. 만약 토끼를 다 잡았더니 사슴이 와서 농작물을 먹는다면? 이제 농부가 사슴을 잡는 플레이어에게 보상을 주겠죠. 아까 드래곤의 예로 돌아가면, 마을 사람이 다른 마을 사람을 DESIRE하게 하면 마을 사람을 잡아먹는 드래곤을 잡는 플레이어에게 마을 사람이 보상을 줄 수 있겠죠. 녹 괴물이 마을의 금속을 잡아먹으면, 마을 사람 중에 금속을 DESIRE하는 대장장이만 녹 괴물에 현상금을 걸겠죠. 이거 구현이 좀 까다로운 게 농부에게 기억력registry을 줘야 되고 토끼를 제3의 오브젝트인 농작물을 통해서 농부에게 기억시켜야 하는 데다가 플레이어 액션도 제 3의 오브젝트인 토끼를 통해 농부에게 릴레이되어야 했었죠. 구현이 까다롭다보니 우선순위에 밀리고 급한 일 처리하느라 결국 구현을 못 했습니다. 사실 이거 제안할 때 테스트 케이스는 삼각관계였습니다. Bob도 HUMANFEMALE을 DESIRE하고 Fred도 HUMANFEMALE을 DESIRE하다가 둘 다 Nellie에게 정착하면 서로의 DESIRE를 두고 경쟁하는 상대방을 죽여달라고 플레이어에게 부탁하는 거죠. 그러다 Nellie가 드래곤에게 잡혀먹히면 둘 다 드래곤을 죽여달라고 플레이어에게 부탁하고(...) 이거 말고도 NPC의 이동경로를 수동으로 세팅하기보단 피로도FATIGUE를 도입해서 밤엔 자게 한다든가, 하루의 시간이 지나감에 따라서 SHELTER가 집이었다가 일터였다가 바뀌게 한다든가, 준법시민은 DARK를 aversion하게 해서 도둑들이 어둠속으로 다니게 한다든가 하는 등의 아이디어가 있었습니다. 이쪽에서 제일 하이레벨 인터페이스는 마을에서 누군가 스토리를 외치고 다니게 만드는 거였죠. "농부 Hayseed가 농작물이 자꾸 망쳐져서 걱정이랍니다!" "Fred가 Nellie에 대한 질투 때문에 Bob을 죽였다고 합니다!!" 하는 식으로..
6. 문제들 리소스 시스템 구현은 대부분 동적으로 조립된 텍스트에 기반하고 있었는데, 로컬라이즈할 때 큰 문제가 되어서 많은 부분이 static text로 대체되고 대사들의 맛이 사라졌습니다. 이건 만들고 보니 거의 스폰과 기본적인 행동양식을 시뮬레이션하는 인공생명 시뮬레이터에 하이레벨 퀘스트 시스템을 합쳐놓은 수준이었습니다. 그런데 다음과 같은 요소가 없으면 이런 걸 열심히 만드는 게 별로 의미가 없을 것 같습니다. * 플레이어에게 인과율을 드러낼 것. 그렇지 않으면 랜덤이나 마찬가지.
* NPC가 원하는 걸 플레이어에게 전달하고 원하는 걸 채워주면 응답하게 할 것.
* 스태틱 데이터는 가능한 피할 것. 근데 전통적인 게임 개발팀에선 좀 무리다.
* 변수들이 항상성을 가지게 할 것. 인공생명 시뮬레이터는 보통 발산하는데 플레이어에겐 재미없는 현상입니다.
* 리소스를 닫힌 계로 만들지 말 것. 플레이어가 리소스를 모아두는 게 큰 영향을 미친다.
* 길찾기와 탐색에 CPU자원이 엄청나게 드니까 구현 가능한 수준으로만 만들 것. 마지막 문제의 경우 옛날에 MUD제작 커뮤니티에서 이런 얘기를 좀 한 바에 의하면 시뮬레이션 수준에 LOD를 두거나, 마지막 인터랙션한 시간 타임스탬프를 찍어놓고 다음번 인터랙션할 때 한꺼번에 시뮬레이션하거나, 힐클라이밍+브로드캐스팅을 쓰는 방법 등이 있었습니다. 이미지 프로세싱 기술은 잘 최적화되어있으므로 여기에 활용할 수 있을 것 같습니다. 닫힌 계는 확실히 실수였는데 현실세계에서는 대부분의 리소스가 사실상 무제한이고, 제한이 있는 게 재미있는 경우는 보통 지역적으로만 리소스가 모자라는 경우입니다. 인과율을 드러내는 건 일이 좀 많긴 하겠지만 하면 될 것 같습니다.
7. 결론 마음속으로는 이 리소스 시스템을 여러 가지 방법으로 발전시킬 구상이 있습니다. 어느 시점이 되면 지금처럼 정적 데이터와 1회용 퀘스트를 산더미처럼 쌓아놓은 MMORPG보다 견고한 시뮬레이션 모델을 만드는 게 싸게 먹히게 될 겁니다. 솔직히 CPU를 혹사시키는 문제에 있어서는 이 시스템보다 3D 충돌 체크가 더 심할 거라고 보는데, CPU 파워가 점점 강해지고 있으니 더 많은 가능성이 열릴 겁니다. 오랫동안 일해오면서 핸드크래프트주의자에 비해 시뮬레이셔니스트들이 좀 힘든 길을 온 것 같습니다. CPU파워가 빨라지는 속도가 사람이 손으로 시나리오를 만드는 속도보다 빨라지고 있습니다. 언젠가는 현실이 1995년에 디자인한 그 세계를 따라잡게 되겠지요.
  • 9 replies