11/30~12/1까지 이틀 간 버닝비버 행사를 테스터로서 초대받아 참가하였다.
조금 늦었지만 다시 프로젝트에 집중을 하려하며 행사에서 보고 경험했던 것들이 추후 게임을 제작하며 우리 팀이 나아가는 길에 좋은 거름이 되었으면 좋겠다는 바램이다.
먼저 맵 R&D에 앞서 Node 와 Map으로 나눠놓은 스크립트가 제일 중요하게 작동된다.
MapManager등의 이외 스크립트들은 이 객체들로 이루어진 비주얼라이징 요소이기 때문이다.
Node스크립트는 Vector2와 mapType으로 이루어져있다. Vector2는 노드의 위치를, mapType은 노드의 맵요소를 담아두는 타입이다.
MapType스크립트는 mapType으로 이루어져 있으며 각 맵타입의 확률계산도 여기서 이루어질 것이다.
전투 승리 이후 카드 3장을 선택 할 수 있도록 하는 시스템을 구축하였다.
먼저 조건으로는
// 레어도 가중치에 대한 비율 계산:
// Common = 12 / (12 + 5 + 2 + 1) = 0.6 (60%)
// Uncommon = 5 / (12 + 5 + 2 + 1) = 0.25 (25%)
// Rare = 2 / (12 + 5 + 2 + 1) = 0.1 (10%)
// Legendary = 1 / (12 + 5 + 2 + 1) = 0.05 (5%)
이렇게 가중치를 주어 각각의 카드가 나오는 확률을 계산하였다.
가충치를 위 순서대로 딕셔너리를 <Rarity, weight(확률값)>으로 제작하고 순차적으로 더해줘서 각 레어도 조건에 맞는 값을 가진다면 그 레어도를 가진 카드 중 랜덤하게 섞인 리스트에서 뽑아내는 구조로 되어있다.
카드는 Basic과 Special을 제외한 모든 카드가 들어간 리스트를 제작하고 그 리스트를 랜덤하게 섞은 뒤 위에서 설명한 시퀀스대로 산출을 하여 총 3장을 뽑아낸다.
Basic과 Special을 제외한 이유는 Special은 기본적으로 특수한 이벤트 또는 특수한 기믹에 의해 얻어지는 카드들이고 Basic은 기본카드로 추가로 획득을 불가능하게 하여 덱성장이 정체되는 것을 방지하는 목적이다.
현재 제작한 시스템은 문제 없이 돌아가지만 상점과 이벤트 내 랜덤 카드 획득 등 다양한 조건에서 폭넓게 사용을 할 것으로 예상이 되어 기존 3장만 뽑도록 제작해 둔 것을 임의의 정수를 넣어 원하는 만큼 시스템에 맞게 뽑을 수 있도록 변경하였다.
//// 랜덤 카드 산출 시스템 내 카드 뽑기 메서드 ////
public void PickRandom3CardWithRarity(int num)
{
cardChooseList.Clear();
for (int i = 0; i < num; i++)
{
card_data card = GetRandomCardByRarity();
if (card != null)
{
cardChooseList.Add(card);
cardDefaultList.Remove(card);
}
}
cardDefaultList.Clear();
foreach (var card in CardInfo.Instance.cardDic)
{
if (card.Value.unlock && card.Value.rarity == "CARD_RARITY_BASIC")
{
cardDefaultList.Add(card.Value);
}
}
}
}
제작 이후 다른 작업 도중 보스클리어 또는 아주 특수한 상황에 따라 최고등급의 카드만 뽑을 수 있도록 하는 장치가 필요하다고 판단하여 그것 또한 마련을 하였다.
처음 카드 데이터를 만들 때 별 생각 없이 카드 stat 부분에 처리를 하여 공격, 방어, 드로우를 한 값으로 통일 시켜 사용하다보니 다른 수치들과 같이 쓸 경우가 생겨 버프 디버프 쪽으로 만들다가 기존에 stat에서 사용하던 것과 버프 디버프로 사용하는 것 2가지 방법이 같은 효과를 가지고 있게되는 문제를 발생시켜 결국 데이터에 추가 프로퍼티를 만들었다. 카드를 만들 때 세세한 부분은 추후에 시스템들이 정립된 다음 만들고자 미뤄둔 것이 터진 것이다.
이 문제는 인원에 따른 개발력 부족으로 인해 우선순위를 어쩔 수 없이 나눠 진행한 것이 발단이 된 것으로 보인다. 처음 제작하는 게임이지만 이번 일을 통해 적은 인원이고 개발력이 부족하다고 해서 지금 당장 고칠 수 있는 문제들을 뒤로 미룬다는 것은 추후에 더 큰 문제가 발생할 확률이 높다. 개발력이라고 하는 것이 프로그래밍 같은 기술 개발만이 아닌 기획, 마케팅 등 모든 부분에서의 부족을 의미하며 경험의 부족을 의미한다. 즉 이번과 같은 일들을 겪으며 이 경험들을 쌓아올려 더욱 더 좋은 게임을 만들겠다는 마음이 더 굳어지는 것 같다.
또한 지금 만들어둔 시스템들도 최대한 유저나 개발자 모두가 이용하는데 문제가 없도록 만들고 있지만 더욱 더 세심하고 편안하게 느껴지도록 제작을 해야겠다는 생각이 든다.
이벤트를 실제 적용시켜서 플레이어 데이터에 연동을 하려고 보니 각각의 리워드 별로 타입도 다르고 수치가 들어가는 것과 각각의 클래스 데이터들이 들어가는 것 등 다양한 변수들이 발생하여 현재의 구조로는 후속 이벤트 등의 처리에 문제가 발생할 것이 확실해져서 이것을 해결해 보려고 한다.
현재 사용하고 있는 데이터는 ID, NAME, DESC, BTN1_DESC, BTN1_REWARD_TYPE, BTN1_REWARD_VALUE의 형태로 하나의 객채가 만들어졌고 Value의 종류와 조합이 많아져 Type을 한개로 처리하기에 벅차다는 문제와 후속 이벤트 처리가 불가능 할 정도로 빡빡하게 짜여진 틀이 문제가 되어 이 부분을 해결하고자 한다.
해결 방안으로 이벤트 테이블과 리워드 테이블을 나누어 리워드 테이블에서는 Type, Value는 형태는 그대로 유지하되 Value를 객체로 받아들여 다양한 조합들이 가능하도록 만들 것이며, 각 Type에 따라 여러 개의 타입도 같이 적용 시킬 수 있는 Reward라는 Parent Value를 만들어 진행하려한다.
이벤트 테이블의 경우 기존의 형태를 유지해도 문제가 되지 않기에 뒤에 붙은 리워드 부분만 제거됬을 뿐 기존과 동일하게 유지가 됬다.
이렇게 진행한다면 리워드를 각 타입별로 Switch 문을 사용하여 처리하려고 하며 Switch 문 코드를 제외한다면 이벤트 매니저에서도 수정만 가해질 뿐 전체적인 틀은 그대로 유지할 수 있어 결과는 더 좋게 바뀌지만 작업량은 반감이 되는 좋은 형태로 설계해보았다.
오늘부터 작업을 시작하여 번역 데이터가 2배가 되겠지만 나머지 부분이 어렵지 않게 이식이 될 것 같아 결국 전체로 본다면 예비로 준비해둔 모든 이벤트를 클래스로 만드는 것보다 좀 더 빠른 시기에 작업이 완료되며 관리하기 어렵지 않게 될 것으로 보인다. 물론 클래스로 만들어서 관리하는 것이 좀 더 편하고 불변하지만 이렇게 틀이 갖추어진 시스템을 가지고 있다면 적은 수의 작업에서는 클래스로 만들어서 하는 것보다 효율이 안좋을 진 몰라도 대량으로 이벤트를 제작할 때는 오히려 더 작업속도가 좋은 형태를 가지고있다.
이벤트를 처리할 때 다양한 방법이 있고 각 방법마다 장단점이 있듯이 모든 기술에는 장단점이 있다. 이것을 잘 파악하여 우리가 사용함에 있어 어느 것이 나을지 판단을 항상 해보는 것이 중요하다고 생각한다.
이것과 별개로 오늘 회의를 진행하였다.
회의의 첫 주제는 이벤트 시스템 개편 및 구조에 대해서 얘기를 나눴다. 구조를 이벤트 테이블 하나로 모든 걸 처리하고 있었던 것을 리워드 테이블로 나눠 좀 더 다채로운 처리를 가능하도록 만들었다.
두번째 주제로는 도전할 사업공고에 대한 내용이었다. 이 부분은 지금 여기에 공개하기엔 준비가 부족하여 진행상황에 따라 공개를 하도록 하려고 한다.
세번째 주제는 우리의 색을 입히기 위해 어느 부분이 어떻게 필요한 가였다.
우리가 가져가야 할 것은 두가지라고 본다. 다채로운 이벤트와 전투에서의 특수 시스템 도입이다. 이 부분은 좀 더 간추려지면 내용을 추가하도록 하겠다.
이벤트를 어제 회의에 맞게 이식을 하며 작동을 하도록 하여봤다. 작동은 하지만 원하는 만큼 유동적으로 처리가 되지 않고 오히려 불편해진 느낌이었다. 그리하여 좀 더 개선을 거쳐서 좋은 방향으로 발전하도록 노력을 해보려고 한다.
불편한 점으로는 대부분의 이벤트들을 각 타입에 맞게 적용을 시켰지만 확률이 들어간 이벤트라던지 한번의 클릭으로 끝나지 않는 이벤트의 경우 문제가 생기는 것을 확인하였다.
이 부분 등 좀더 견고한 구조 및 문제가 일어나지 않도록 구조를 재정립하고 이벤트를 진행시켜보려고하며 이것이 완료되면 바로 맵 시스템을 마저 구축할 예정이다.
새로 게임을 진행해볼때마다 포기 - 시작 -진행 순으로 실험을 하고있었는데 전투 씬을 들어갔다가 포기하고 재시작시 기존 몬스터 풀이 줄어드는 문제를 발견하였다. 처음에 재현이 안되어 문제가 발생했던 팀원에게 정확한 상황을 듣고 동일한 방법으로 계속 시도해보니 같은 문제가 발생하였다. 이 문제는 랜덤산출 스크립트에 초기화 코드가 싱글턴 인스턴스화 될때마다로 정의를 해두어서 새로 시작시 초기화가 되지않고 몬스터를 계속 뽑아내어 생기는 문제였다. 싱글턴의 경우 static으로 상시 메모리에 할당되있다는 점을 간과하여 생긴 문제이다. 다음에 싱글턴을 사용하여 내부 메서드 등을 사용할 때 초기화가 필요한 경우 무조건 쓰도록 장치를 구비해야겠다는 생각이 들었다.
원하는 시점에 초기화를 해주는 코드를 넣고 초기화시 기존 몬스터풀이 남아있는 경우 랜덤하게 뽑지않고 그대로 유지되도록 작동을 하여 몬스터 풀이 줄어드는 문제를 해결하였다.
이벤트를 원하는 구조로 완성하고 이것을 비주얼라이징하여 실제 작동하여 게임 데이터에 연동 시키는 것을 목표로 1주일 간 진행하였다.
대부분의 시간을 구조 및 구조 이식에 사용하여 학습을 해보았고, 지금처럼 전체 사이클을 돌려보는 경험이 한번이라도 있었다면 이렇게 구조를 짜지 않았을 것이지만 그렇지 않은 상태에서 현재 내가 할 수 있는 최선의 방법으로 진행하였다.
밑의 사진과 같이 엑셀 데이터들을 받아 딕셔너리로 정리해 준 후 현재 이벤트 ID를 통해 딕셔너리를 산출하여 현재 버튼에 부착될 정보들을 불러와 사용하였다.
처음에 문제가 된 것은 같은 버튼에 들어가는 자료의 ID를 똑같이 사용하여 1개로 덮어씌워지는 것을 알게되었다. 딕셔너리를 사용할 때 같은 ID를 쓸일이 없고 제대로 알지 못한 상태에서 사용하다보니 이런 문제를 일으킨 것이다. 이를 통해 구조를 잡을 때 다양한 조건을 미리 파악하고 그 조건도 포함될 수 있는 구조로 제작을 해야 할 것으로 보인다.
마지막 영상은 이벤트를 실제 적용하여 데이터에 연동시킨 과정을 보여주는 영상이다. 이후 작업할 것은 전에 작성한 이벤트들을 지금의 구조로 이식하고 데이터를 연동시켜 보는 작업을 하고 이후 이벤트 풀을 늘려나가며 맵을 제작할 예정이다.
후속 이벤트 등 이벤트 처리가 완료되었고, 모든 이벤트가 이식이 되었다.
오늘 발생했던 문제는 기존에 저장을 했던 gamesave_data.Instance.selectedEventIDs가 selectedEventID로 덮어씌워져서 무슨 문제인지 살펴보니,
기존에 있던 리스트에 selectedEventID만 넣어주는 코드로 되어있었고,
gamesave_data.Instance에서 받아오는 코드는 gamesave_data.Instance.selectedEventIDs가 존재할 시 넘어가도록 되어있어서 싱글톤 구조와 맞물려 문제가 생기던 것이어서 싱글톤 인스턴스가 존재하더라도 받아오도록 하여 해결하였다.
이후 몬스터와 카드, 이벤트들을 늘려 볼륨을 키우는 과정에 있고, 맵까지 완성을 한다면 나머지 모든 구조가 완성이되어 한 사이클이 돌아갈 수있게 된다.
며칠 간 밤을 새고 나서 휴식을 취하며 미뤄놨던 생각들을 정리하였다. 여러 사업들에 참가를 함에 있어 다양한 심사위원님들을 만나게 되었을 때, 게임업계와 연관이 있으신 분들이 계실 수 있고, 게임업계와 연관이 없으신 분들이 계실 수 있다는 생각이 들게 되었고, 그렇다면 게임을 잘 아시는 분들과 게임을 잘 모르시는 분들 모두를 만족시키며 내용을 재밌게 풀어나갈 수 있는 방법을 생각해 보게 되었다. 자본이 연관돼있는 사업이기에 무거운 분위기로 이어지겠지만 게임을 주제로 하는 것이기에 무겁지만 재미있게 생각들이 공유가 되는 자리가 되었으면 하는 마음이 들게 됐다.
먼저 게임이 어떻게 사람들에게 보이는 것인가를 생각해 보았다. 게임은 컴퓨터로 작성된 여러 요소들이 화면으로 보이는 것이다. 그렇다면 이것을 비슷하게 연관되는 것들이 무엇이 있는지 생각을 해보니 화면에 보여준다에서 영감이 드는 것은 모니터에서 보이는 것, 텔레비전에서 보이는 것, 영화관에서 빔프로젝터로 스크린에 비치는 것 이렇게 세 가지가 스쳐 지나가듯 떠올랐다. 이 세 가지에 동시에 보이는 것이 무엇일까를 생각하니 영상콘텐츠가 세 가지 모두에 포함이 되는 것을 떠올리게 되었고, 게임도 유저의 상호작용을 제외하고 본다면 화면에 비치는 영상콘텐츠로 생각이 되었다. 그렇다면 이 영상 콘텐츠를 설명할 때 세대와 관계없이 이해가 되려면 각각의 시대별로 영상콘텐츠를 감상을 했던 경험을 떠올려야 한다고 생각했고, 한국의 심사위원들을 대상으로 하기에 한국에서의 각 세대별 영상콘텐츠의 경험을 위주로 설명하는 것이 좋겠다고 생각하였다.
우선 우리의 부모님 세대 또는 조부모님 세대 분들이 영상매체에 대해 얘기했던 내용들이 떠올랐다. 우리 조부모님의 말씀에 따르면 텔레비전이 각 가정에 보급되던 시기가 대략 50대이실 시절이라고 하셨고, 부모님의 경우 20~30대 시절이라고 하셨다. 그렇다면 조부모님들이 20~30대 또는 40대 시절에는 각 가정에 보급되기 이전에 전자제품 판매점 등에서 접할 수 있었기에 텔레비전이 있는 집, 또는 전자제품 판매점에 모두 모여 영상매체를 시청했다고 한다. 그렇다면 20~30대인 우리는 어떠한가 어려서부터 텔레비전이 이미 집마다 있고 그것을 통해 언제든 영상매체를 접할 수 있었다. 즉 현재 사업을 심사하시는 분들 또한 영상매체에 대한 경험이 있다고 할 수 있고, 우리가 전달하고자 하는 내용들을 영상매체에 빗대어 표현한다면, 세대와 상관없이 이해를 하는 데 있어 용이할 것이라고 생각이 들었다. 먼저 게임을 영상매체라고 가정하고 설명을 시작해 보자.
심사위원 분들 또는 유저들을 영상매체를 감상하기 위해 모인 사람들이라고 가정을 했을 때 게임에서의 유저 편의성은 감상환경이라고 생각이 된다. 감상환경이란 전자제품 판매점일 경우 맨바닥 또는 불편한 의자일 것이고 영화관일 경우 편안한 감상용 의자일 것이고 가정이면 바닥 또는 사무용 의자일 것이다. 부모님의 말씀을 빗대어 볼 때 영상매체를 감상할 때 자리는 불편했지만 영상매체에 대한 기대로 항상 자리를 잡고 계셨다고 했다. 그렇다면 불편함이란 게임에서 유저의 편의성이 충족되지 못했을 때라고 생각한다. 아무리 게임이 재밌다 할지라도 유저의 편의성에 대한 배려가 없다면 영상매체를 다 감상하고 영상매체에 대한 내용이 생각되는 것보다 불편함이라는 것이 먼저 생각이 된다는 것을 보면, 온전히 자신 또는 팀이 제작한 게임을 전달하고자 한다면 우선적으로 유저 편의성에 대한 배려를 충분히 할 필요가 있다고 생각한다.
이제 유저의 편의성이 갖추어져 있다고 가정을 하고 메인 디쉬인 영상매체 즉 게임을 생각을 해보자. 영상매체가 재미가 없다면 언제든 관객들은 떠나갈 것이다. 그렇기에 그들을 만족시키기 위한 재미가 충분히 보장되어야 한다. 그렇다면 재미가 무엇인가라고 본다면 큰 카테고리인 영상매체에서의 재미는 비주얼과 연출이다. 보는 사람들로 하여금 영상 내의 분위기와 내용이 잘 전달되게 하여 즐거움을 만들어 내는 것이다. 이제 세부 카테고리인 게임에서 생각을 해보자. 먼저 영상매체와 같은 비주얼과 연출의 재미가 1차적으로 준비가 되어 있어야 하며, 2차적으로 게임이 줄 수 있는 재미인 유저와의 상호작용이다. 유저와의 상호작용은 핵심 메커니즘과 코어루프, 밸런스가 잘 갖추어져야 즐거움이 만들어진다. 관객들이 즐거울 수 있는 핵심 메커니즘, 핵심 메커니즘을 연속적으로 경험하며 즐거움을 끊기지 않게 해 주는 코어루프, 앞서 2가지를 경험함에 있어 불편하지 않게 해 줄 잘 맞추어진 밸런스 이렇게 3가지와 같이 비주얼과 연출을 합하여 만들어진 복합적인 재미가 게임의 재미라고 생각을 한다.
그렇기에 이제 심사위원 분들과 유저들 또는 유저가 아닌 일반 관객들에게 우리를 표현한다면 모든 사람들이 감상하기 편하도록 편안한 의자를 마련을 하고 감상을 할 수 있는 화면 장치를 마련하고, 언제든 들어왔다 나갈 수 있는 편안한 환경을 제공하는 것으로 시작을 해서 재미있는 영상콘텐츠를 제공하고 영상 콘텐츠에 상호작용하며 즐거움을 느끼게 하고 감상을 마치고 나갈 때까지 불편함을 없도록 서비스하는 사람들이라고 생각한다.
그렇다면 이제 이 핵심 내용을 가지고 각 세대별의 사람들이 이해를 편하게 하기 위해선 각각의 사람들이 가지고 있는 경험을 토대로 영화관, 전자제품 판매점, 가정 등 다양한 환경 중 제일 기억에 남는 환경에 빗대어 설명을 한다면 더 좋은 공감을 이끌어 낼 수 있을 것으로 판단된다.
개발 기록을 위해 찍어둔 영상과 사진이 엄청나게 많지만... 글을 쓸 짬이 나질 않아 신경을 못 쓰고 있습니다. 홈페이지도 계속 업데이트 시키고 있구요.
첫 일정이 마무리 되었던 19일 이후로 버그 수정 및 알파 빌드를 하기 위한 R&D를 지속하고 있으며 12/30일자로 마무리되는 공모와 1/14일 마무리되는 입주사업에 대비하여 프로젝트를 좀 더 업그레이드 시킬 필요가 있어서 개발일지를 적을 시간 없이 작업을 하고있었습니다.
좋은 결과가 있었으면 좋겠지만 어떤 결과든 나아가기 위해 한걸음 한걸음 진행해갈겁니다.
오늘 작업을 마무리하며 로그라는 게임을 해보기로 하였다. 플레이 해보며 왜 로그라이크 게임들이 로그라이크인지와 어느 부분들을 차용했는지 와닿았다.
먼저 로그의 시스템을 보자면 크게 2가지이다.
1. 죽으면 초기화되며 처음과 동일한 조건에서의 시작
2. 랜덤 요소
먼저 죽으면 초기화되며 처음과 동일한 조건에서의 시작은 말 그대로 죽은 뒤 어떻게 다시 시작이 되는 가에 대한 방식의 차이이다.
다음으로 랜덤요소이다. 절차적으로 생성되는 맵, 감정하기 전까진 어떤 효과를 가지는지 알 수 없는 암호화된 스크롤 및 장신구로 구성되어있다.
절차적으로 생성되는 맵과 죽으면 초기화 되는 방식의 조화는 오래된 게임이지만 상당한 재미를 지금도 느낄 수 있었으며, 픽셀 던전과 같이 로그에 가깝게 제작된 게임의 경우 로그를 플레이하기 전까지는 이 게임들이기에 재미가 있다고 생각을 했지만, 로그를 플레이하고 나서는 게임이 가지고 있는 고유의 재미보단 원판에 있는 재미를 좀 더 각각의 시대상에 맞게 적용을 시킨 것에 가깝다고 생각이 된다.
다음으로는 최근 많아지고 있는 슬레이 더 스파이어 + 동료 시스템들이 어떤 느낌을 살리고자 하는지 알기 위해 위저드리를 플레이 해볼 예정이다.
아마 다음 작업이 마무리 되고 나서 플레이 해볼 수 있겠지만 시간을 만들어서라도 빠르게 플레이해보는 것이 도움이 될 것이라고 생각한다.