Unity New Input을 이용하여 게임패드와 마우스, 키보드 등 다양한 입력기기들을 연동시켜보았다.
마우스나 키보드 같은 경우 이미 정해진 레이아웃이 있지만
게임패드의 경우 디폴트 레이아웃을 제외한 나머지 버튼들은 각 컨트롤러의 이름으로 레이아웃이 지정되어있다.
굳이 나누지 않겠다고 한다면 디폴트레이아웃 + 나머지 버튼이지만 좀 더 안정적으로 컨트롤러를 지원하고자 한다면 크게 XBoxController, PlayStationController, DefaultController 이렇게 3가지로 나누어서 적용할 수 있을 것이다. 각자의 개발환경 또는 출시환경에 따라 다른 컨트롤러를 지원해야하기 때문에 각자의 환경에 맞춰 지원할 수 있도록 New Input에서 어떤 레이아웃을 제공하고 혹여 없더라도 어떤 레이아웃에 어떻게 추가를 해야하는 지에 대한 연구가 필요하다.
스토리 작업을 1차 마무리를 지었다. 아직 많이 부족하며 허점이 많은 스토리지만 팀원에게 어떠한 느낌으로 표현하고자 하는지는 전달이 30%정도 된 것 같다. 좀 더 가공을 하며 진화시켜나가야겠지만 다른 작업을 우선시하며 병행을 하도록 하려고 한다. 목표로 하고있는 11월 말까지 베타를 완성하려면 나머지 시스템들과 카드의 밸런싱을 맞추는 것을 우선시하고 나머지 연출 및 비주얼적인 요소는 회의를 통해 맞춰나가면서 팀원이 진행하도록 하려고 한다.
스토리라는 것은 많은 경험과 문학적 깊이가 있어야 좀 더 좋은 내용이 나오는 것은 당연한 것 같다. 하지만 그냥 문학적 깊이가 있는 것과 함께 평소 다른 경험들을 해봐야 새로운 아이디어를 통해 자신이 표현하고자 하는 것을 같은 메세지를 가지고 다른 느낌으로 만드는 것을 해낼 수 있다고 본다.
이제는 지금까지의 경험으로 해결을 해야하지만 조금 더 경험을 쌓으며 문학적 지식을 늘려놨으면 어땠을까 하는 생각이 든다.
하지만 경험과 지식이 적다고 해서 포기할 필요는 없다. 부족한 부분을 정확히 알았기 때문에 자신이 할 수 없는 일과 할 수 있는 일을 확실하게 나눠 시간을 소비하는 것이 아닌 또 다른 기회의 시간으로 만들면 되는 일이기 때문이다.
이번 주는 맵 시스템을 점검하며 우리의 스토리라인에 맞게 어떻게 표현해 나갈지에 대해 고민을 하며 1차 프로토타입을 제작해볼 것이며, 동시에 카드를 정비하여 첫 플레이에 나올 카드들과 이후 나올 카드들에 맞춰 정리를 해둘 예정이다.
1막의 몬스터는 체력을 평균 40~48정도를 가진다. 20체력 같이 낮은 체력을 가진 적은 2마리씩 나오며 기믹으로 인해 실드 등으로 48에 도달할 수 있다. 또한 체력이 40~48정도를 가진 적들은 1마리씩 나오며, 엘리트 몬스터의 경우 평균보다 데미지가 25% 상승되있으며 체력은 2배에 달한다.
보스의 경우 3~4배에 달하는 체력을 가지며 데미지는 평균 데미지보다 50% 상승되어있으며 기믹과 동반된다.
2막의 경우 평균 80~96정도를 가지며 평균 체력을 가진 적들이 2마리씩 나오게 된다. 체력 자체에 영향이 없는 걸 보아 숫자로 밸런싱한 것으로 보인다.
3막의 경우 120~144정도를 가지고 있으며 엘리트, 일반 몬스터 중 평균 적지만 2~3마리씩 같이 나오는 경우가 많다.
캐릭의 체력을 보면 80 최대체력으로 체력관련 유물을 먹지 않을시 마지막까지 80을 유지하게된다. 1막에서는 평균 적보다 체력이 2배 많고 2막에서는 평균과 같고 3막에서 0.5배 적은 것으로 보아 각 챕터의 난이도를 대략적으로 볼 수 있다.
또한 기본 공격카드의 데미지는 6 방어카드는 5이다. 첫 전투 및 1막의 적을 상대로 데미지를 계산해보면 공격카드만 썼을 시 최소 2.5턴을 소모하게 되며 그 동안 공격을 받을 시 12*2로 24데미지를 받게된다. 이를 통해 2.5턴이라는 꽤 짧은 턴 안에 많은 데미지를 받게되기에 유저가 경험을 하며 다시 시작하게 됬을 시 무조건 공격이 아닌 방어카드를 자연스럽게 섞게된다.
이를 바탕으로 우리가 만들 게임 또한 기본 데미지를 기준으로 2.5턴을 목표로 전투를 지속시켜야하며 적의 데미지 또한 납득 가능할 정도의 수치로 줘야 자연스럽게 방어를 하면서 생각을 계속하게 만들어 턴제라는 느린 템포를 체감상 빠른 템포로 느끼게끔 변경시킬 수 있다. 또한 기본 카드 등 1코스트의 낮은 수치의 카드들로 지속적으로 데미지를 줄지 중후반에 나오는 2~3코스트의 높은 수치의 카드들로 한번에 데미지를 줄지 선택지를 주어 예를 들어 아이언클래드(전사)의 느리고 강한 공격이라는 고정관념을 깨고 기본 카드들을 3장씩 쓰며 템포를 빠르게 하고 있다. 이 템포를 유지할지 조절을 할지는 유저에게 달려있다는 말이다.
툴을 작성하여 Excel을 임포트하여 JSON과 CS를 만들어 냈으며 각각의 Data.cs를 싱글톤으로 구현하여 불변성을 갖추었다. 현재 Don'tDestroy를 남발하여 fps가 많이 튀는 것을 확인하였으며 전체 데이터 구조를 다 잡고 난 후 최적화를 할 예정이다.
툴을 하나 더 만들어서 Save&Load 구현시키며 JSON 파일들 중 게임 플레이와 직접적으로 연관 없는 파일들을 스팀클라우드에 연동시키기위해 수치 변동이 없도록 하였다. 또한 DataManager를 그대로 사용하여 MainMenu의 버튼들과 연동시키려 하였으나 그러기 위해 인스펙터에 어사인하는 방법 외 다른 방도가 보이지않아 부득이하게 싱글톤으로 변경하였다.
지금까지 데이터 구조들을 잡으며 변동치를 주려고 생각했던게 잘못됬던 것 같다. 변동치를 받지않는 불변 데이터들을 유지시키며 거기서 파생된 데이터들을 이용하여 인게임의 구조를 잡으려하며 불변 데이터들과 실제 플레이데이터로 저장된 JSON을 스팀 클라우드에 연동시켜 Unlock된 카드라던가 여러가지 리셋이 되면 안되는 데이터들을 저장하여 추후 게임을 삭제하고 다시 설치한다던가 업데이트시 문제가 벌어질 것이 확실하여 그 부분을 수정하였다.
오늘 오전, 오후엔 프로젝트를 진행하였고 팀 분위기를 리프레시하기 위해 타임스토리즈 보드게임을 해보며 분석을 하고 우리가 게임을 계속 만들어가면서 어떤 방식으로 시스템과 테마를 잘 녹여내야하는지 알아보는 시간을 가졌다. 전체적인 스토리와 진행방식은 D&D와 같이 게임마스터가 전체적인 스토리를 참여자들과 공유하고 정해진 시간 안에 맵을 탐험하며 주어진 목표를 완수하는 게임이다. 먼저 첫 맵으로 넓은 홀이 있었고 파노라마형식으로 맵이 주어진다는 점이 신기하였다. 각 캐릭터의 특성에 맞춰 디메리트와 메리트가 있었으며 이에 따라 진행방식이 차별화되었다.
우리는 참여자가 2명이면서 캐릭터의 특성이 같이 다니지 않으면 정해진 시간을 소모하는 속도가 가속화 되어 항상 붙어서 진행해야 하므로 맵을 탐험하는데 불이익이 컸다. 아무것도 정보가 주어지지 않은 채 적은 탐험으로 진행해야했으므로 아이템이 부족하지만 마지막 스토리라인으로 준비없이 직행할 수 밖에 없었다.
스토리의 마지막을 봤지만 트루 엔딩이 아닌 데드엔드 엔딩으로 마무리 되어 미션 성공, 실패에 대한 내용도 없이 종료가 된 점은 맵 탐험의 부족에서 오게 된 것으로 느껴졌다. 노멀 엔딩이 아닌 어떤 결말도 없는 데드엔드 엔딩이어서 그런지 다음에 한번 더 도전하고자 하는 마음이 컸던 것 같다.
촉박한 시간과 부족한 탐험, 부족하다는 것을 인지하고 진행했던 마지막 지역 탐사와 보상이 없는 엔딩이 합쳐져 다시 도전하고자 하는 마음으로 경험이 이어진 것으로 판단된다. 여기서 느낀 점은 보상만으로 다시 도전하고자 하는 마음을 얻는 것이 아닌 보상이 없고 부족하지만 다시 도전하게 끔하는 공허함을 잘 경험시켜야 보상이 없더라도 다시 도전하고자 하는 것으로 발전해 나가는 것으로 느껴진다.
인게임을 만들기에 앞서 메인 메뉴 UI 제작을 맡기로 했다. 일단 처음이니 레퍼런스 없이 레이아웃 구상을 목표로 했다. 무료로 사용 가능한 이미지들을 활용하여 만들어 낸 결과는 아래 이미지와 같다.
프로토타입을 만들 때 해상도에 따라 레이아웃이 달라지는 일을 겪은 바가 있어, 캔버스 스케일러를 설정하여 해상도에 따라 크기가 변화하는 것 또한 확인했다.
이번에는 레퍼런스를 구해 미드저니에게 학습시켜 이미지를 생성하는 방식으로 진행해보았다. 미드저니는 유료 구독하여 사용 가능한 AI 이미지 생성기인데, 국내외 가리지 않고 UI/UX 디자인에 많이 사용되는 것 같아 선택하였다. 메인 메뉴의 레퍼런스로 삼은 게임들은 할로우 나이츠, 드레지, 파이어와치 등이 있고, 느낌만 내려했지 동일한 이미지를 만드려는 목적은 아니었다. 따라서 아웃라인이 없으며 게임 로고가 강조될 수 있는 이미지를 만들어냈다.
그렇게 만든 이미지를 포토샵을 이용해 각 레이어를 분리시켰고, 레이어마다 에셋으로 만들어 각 오브젝트 스프라이트에 삽입될 수 있도록 했다. 이후 마우스 위치에 따라 레이어가 따로 움직이는 느낌만 내봤다. 안개가 깔리는 효과도 넣었다가 별로인 것 같아 제외하긴 했다. 참고로 로고에 적힌 'Into the Dome' 은 가제이며 실제 게임 이름은 아니다.
내가 원하는 이미지 제작 과정은 // 1. 미드저니(생성) → 2. 포토샵(수정) → 3. 스테이블 디퓨전(생성/수정) → 4. 일러스트레이터(수정) // 이렇게 되었으면 하는데, 일단 2번까지는 해봤으니 다음에는 3번을 시도해보려 한다.
스테이블 디퓨전은 대표적인 AI 이미지 생성기 중 하나로, 그 중 스테이블 디퓨전 웹 UI는 로컬 PC의 그래픽카드를 사용한다는 특징이 있다. 말그대로 내 PC의 하드웨어를 통해 이미지를 그려내는 것이고, '파일' 로 된 모델이나 LORA를 삽입하여 생성된 결과물을 획일화시킬 수 있다. 무엇보다도 무료로 사용할 수 있다는 장점이 있다. 이토록 유용한 프로그램과 플러그인을 무료로 배포한 두 자비로운 개발자(AUTOMATIC1111, AbdullahAlfaraj)에게 경의를 표한다. 설치를 원한다면 아래 링크를 통해 다운로드와 매뉴얼 확인 모두 할 수 있다.
Stable Diffusion Web UI: AUTOMATIC1111/stable-diffusion-webui: Stable Diffusion web UI
Auto Photoshop StableDiffusion Plugin: AbdullahAlfaraj/Auto-Photoshop-StableDiffusion-Plugin
플러그인까지 설치가 완료되었다면 포토샵의 Batch(선택 윤곽 도구)를 사용해 이미지 생성을 원하는 구역을 설정한 뒤, 프롬프트를 입력하여 이미지를 생성할 수 있다. 이 기능을 통해 미드저니에서 생성된 이미지의 '일부' 를 수정하는 데에 활용할 계획이다.
작업을 하던 중 잠시 머리를 식힐 생각으로 2024년 4월 12일자로 슬레이 더 스파이어 제작자가 올렸던 포스트가 생각이 나 제대로 분석을 해볼 생각으로 읽어보았다.
먼저 슬레이 더 스파이어2를 치킨 누들 수프 같은 게임을 만들겠다고 발표한 바 있기에 자신들이 어떻게 치킨 누들 수프 같은 게임을 만들 것인가에 대해 설명이 되있는 포스트였다.
먼저 첫 내용은 GDC의 끝 무렵에 감기에 걸렸다는 내용이 있었고 발라트로와 같은 게임들을 해보며 편안한 음식같은 게임을 만드는 것에 흥미가 들었다는 내용이었다.
치킨 누들 수프에 대한 설명이 없어 찾아보니 한국의 죽같이 미국에서 감기 등 몸이 안좋을 때 몸을 치유하기 위해 먹는 음식이었다.
그 다음 내용으론 전 세계적으로 게임제작에 있어 참신한 메카닉스, 특이하거나 아름다운 비주얼, 가슴 따뜻해지는 스토리, 게릴라 마케팅, 소설과 같은 소셜 인터렉팅, 그리고 최신 기술들이 포함되어있다. 하지만 이런 것들보다 혼자 조용히 게임을 플레이 할 때가 제일 평화롭다고 느끼며 이러한 게임은 친구들과 예기하는데 즐거움을 표현할 수는 없지만 항상 당신의 곁에 있는 치킨 누들 수프 같은 게임이라고 설명한다.
도전적이고 스트레스가 많고 시각적으로 인상적이며 다양한 사람들과 마주하는 온라인 게임도 있겠지만, 이러한 게임이 아닌 편안하고 여유로운 게임을 하고 싶을 때가 있다. 사람과의 관계가 아닌 게임과의 관계를 통해 편안한 관계를 형성하는 그런 게임을 추구하고자 하는 것으로 보인다.
다음 내용으론 재료와 레시피를 가지고 어떻게 이러한 게임을 만들어 나갈 것인지에 대해 설명이 되어있었다.
재료 :
1) 플레이어의 흐름을 우선시하는 디자인 우선 게임을 만드려는 의지
2) UX에 대한 집착과 마찰을 없애기 위한 프로세스에 대한 존중
3) 플레이어가 게임을 오래할수록 죄책감이나 부끄러움을 느끼게 하는 수익화 전략과 어두운 패턴을 거부합니다.
4) 시각적 충실성보다 접근성과 가독성을 우선시하는 정화한 시각 효과와 컨트롤
5) 플레이어가 항상 노력하는 명확한 목표. 이는 내재적 또는 외재적 동기를 부여하도록 설계될 수 있습니다.
레시피
1) 흐름 상태 파악 : 자신이 즐거움을 느끼는 순간을 찾고 이 느낌을 간단한 프로젝트로 응용을 해보라. 메커니즘에 들어가는 변수들을 생각하며, 그 요소들이 어떻게 구현될지 상상해 봐라
2) 프로토타입 : 진짜 시스템을 만들 필요는 없다. 하지만 핵심 메커니즘이 재밌는지 실험이 더 중요하니 최대한 빠르게 제작을 해봐라
3) Go/No-Go : 프로토타입이 실제로 좋은지 평가할 시간이다. 3가지 단계로 나눠 평가를 해보며 고쳐나가야할 내용을 정리해보자.
4) 게임 확장하기 : 흐름을 기반으로 게임을 구성하여 세계관을 알아가게 하거나, 플레이어가 공간 감각과 전략을 익히도록 만드는 등 최고의 요소만 골라 실현 가능한 계획을 세워라
5) 신뢰의 도약 : 게임에 대한 계획이 확정되었다면 자신의 신념을 100% 믿고 다른사람을 만족시키기 위한 것이 아닌 미래의 플레이어를 위해 게임을 만들어야한다고 믿어라.
6) 실패 : 믿음만으로는 부족해서 실패할 수 있다. 하지만 그 과정에서 얻은 배움으로 이제 더 발전할 수 있으니 다음을 위해 열심히 실패해라
7) 진화 : 자신의 기준을 발전시켜라, 다양한 게임을 시도하고 그 과정에서 자신이 진짜 원하는 방향성을 알아가면서, 경험을 통해 점점 더 나은 게임을 만들 수 있는 능력을 키워가세요.
4단계와 5단계쯤에서 다른, 더 경험이 많은 동료들에게 조언을 구해야 할 수도 있습니다. 내부 플레이 테스트를 실행하고, 아첨의 기미 없이 정직하다고 생각하는 친구들의 그룹을 구성하기 시작하세요. 사람들이 게임의 흐름 상태에 갇히거나 좌절하는 부분을 파악하고 게임의 핵심 경험을 완벽하게 다듬으세요.
값싼 일회성 요령으로 사람들을 놀라게 하려고 하지 마세요. 기본을 얼마나 잘 구현하는지로 사람들을 놀라게 하세요. 게임을 하는 것이 기분 좋은 이유의 기초가 바로 당신이 추구하는 것입니다. 왜 같은 것을 반복해서 하는 것을 즐기는지에 대한 비밀을 밝혀보세요.
이라는 내용으로 되있었고 이것을 기준으로 우리가 추구하고자 하는 바가 과연 유저들에게 다가갔을 때 어떤 느낌일지를 잘 생각하여 적용시켜야겠다는 생각이 들었다.
오늘은 번역을 구현해보았다. 번역 테이블로 이름과 설명 등을 나눠 각 ID별로 정리하면서 KR,EN으로 나눠놨다. 언제든 다른 언어를 추가할 수 있도록 처리를 해놨으며 밑의 사진은 실제 우리가 사용하고 있는 번역 테이블이다.
번역을 적용시키며 제일 먼저 생긴 문제는 동적으로 번역을 하려했던 것이 실력부족으로 인해 반자동으로 처리가 되게끔 되었다. 하지만 동적으로 바꾸는 것보다 직관적이므로 현재는 유지하고 진행하려고 한다.
두번째 문제는 플레이스 홀더에 대한 문제였다. 플레이스 홀더에 들어가는 변수들을 추가하여 번역을 시켰을때 번역이 되기 전 ID플래그들이 string으로 번역이 된 상태로 들어가기에 번역이 다시 안되는 문제가 생겼다.
이 문제는 데이터 매니저 텍스트로 가져올때 번역이 다 끝난 상태로 들고오기에 생긴 문제이므로 번역을 텍스트에 들어가기 직전에 해주는 형태로 변경하여 처리하였다.
https://play.google.com/store/apps/details?id=com.rootgames.dungeonraid&hl=ko
던전 트레이서 AOS
https://apps.apple.com/us/app/dungeon-tracer/id6502634839
던전 트레이서 IOS
던전 트레이서를 해보며 우리가 만들고 있는 덱빌딩 로그라이크 게임과 다른 장르를 혹시 만들게 된다면이라고 생각해보니 퍼즐을 만들어보면 이 경험을 살려서 나중에 다른 게임을 만들어 컨텐츠를 추가하거나 할 때 도움이 되지 않을까하고 던전 트레이서를 아예 만들지 않을 것이지만 도전해봐야 하는 것들을 정리해서 구현해 보았다.
필수 구현 목록
각 이미지는 오브젝트로 구현이 되어야하며 6X6으로 보드를 구성해야한다.
구성이 완료된 보드에서 각 이미지들을 클릭하면 사라지고 그 위치에 UI Canvas에 배치되어 동일한 크기에 월드에서의 위치와 동일하게 배치되어야 한다.
배치된 이미지는 원하는 위치(나는 버튼으로 지정)까지 일직선을 그어 그 사이 점을 지정해 베지어 곡선을 그린다.
버튼을 클릭시 버튼까지 베지어 곡선대로 이동을 완료한다.
던전 트레이서의 전신인 던전 레이드의 베지어 연출을 동일하게 만들어 둘의 차이점을 비교해본다.
현재 구현이 된 것
1) 6X6 보드를 오브젝트 월드포지션으로 구현
2) 구성이 완료된 보드에 각 이미지들을 클릭하면 사라지고 그 위치에 UI Canvas에 동일 위치, 동일 크기로 배치
-- UI로 구성 되어야하는 이유는 실제 게임 상 아이콘들이 도착하는 위치는 UI 이미지이며 그 이미지보다 위의 레이어에서 도착을 해야하기 때문이다.
3) 배치된 이미지를 버튼까지 베지어 곡선을 그린다.
4) 버튼 클릭시 버튼까지 베지어 곡선대로 이동을 완료
여기까지 구현이 되었고 5번인 세부 연출을 좀 더 다듬어서 비슷하게 구현해보려한다.
오늘은 클래스 셀렉션을 구현해보았다. 먼저 해금되기 전의 클래스들은 미리 메인화면에서 체크가 되기때문에 셀렉션 씬에서 보이지 않도록 처리가 되었고 처음에는 첫 클래스가 항상 선택되있게끔 되있으며 이후 클릭을 통해 다른 클래스를 선택하게끔 처리를 해두었다. 클래스 안에는 기본 덱 정보들이 포함되어있어 선택 이후 다음 씬으로 넘어가게되면 그때 플레이어 데이터가 저장되며 기본 덱과 함께 사이클을 시작할 수 있도록 되어있다.
밑의 영상에서 볼 수 있듯 각 클래스를 선택할 시 어떤 클래스가 선택됬는지 지금 당장은 콘솔로만 확인 할 수 있지만 이미지가 제작되면 바로 적용시키도록 진행해놨다. 영상에서 선택 이후 플레이어 데이터를 열어보았을 때 기본 덱 또한 들어가있는 것을 확인할 수 있다.
현재 진행 중인 스크립트 중이며 각각을 병렬적으로 진행시키고 있고 2주간 크런치를 통해 원하는 양의 60%는 구현한 것 같다.
많은 양을 한번에 처리한다는 것은 무리가 가는 일이 맞지만 원하는 게임을 만든다라는 것이 몸을 움직이게 만드는 원동력이다.
다양한 문제에 봉착하고 그것을 해결해내고 해결이 안되더라도 배제하는 것이 아닌 다른 방식을 구상하고 큰 목표만이 아닌 각 스크립트에 해당하는 목표에 도달하게 만드는 것부터 하나하나 쌓아올려 하나의 큰 목표인 게임을 만든다라는 점은 분명하다. 이 쌓아올리는 과정이 고통스러울 순 있지만 아마 이렇게 게임을 만드시는 모든 분들이 거쳐온 과정이기도 하고 이 고통조차 느껴지지 않을 정도로 결과를 냈을 때 오는 카타르시스는 지금까지 내가 해온 일들에서 왔던 달성의 즐거움들보다 제일 클 것이라고 생각한다. 실제 봉착했던 문제가 풀려 멈춰있던 작업들이 진척이 있을 때 지금껏 느꼈던 고통들에 단비같은 느낌으로 리프레시가 되었다.
작업 중간에 항상 다른 사람들은 쉰다고 생각하지 않았지만 우리 프로젝트 이상으로 발전해나가기 위해 여러가지 기술들을 경험하고 실험하는 과정들이 내가 포기하지 않고 멈추지 않게 해주고있다.
이러한 문제들을 겪어내고 지금까지 포기하지 않고 게임을 제작해온 모든 분들에게 존경을 표한다.
클래스 선택 씬에서 각각의 데이터들이 들어오지 않는 문제를 발견하여 문제를 해결해 보았다.
클래스인 Watch 선택 후 각각의 Watch에 맞게 카드가 들어와야하는데 카드가 들어오지 않아 확인해보았다.
.Append(카드)로 옛날 Python에 익숙해져 있는 방식으로 확인하지 않고 머리 속으로 시뮬레이션하며 작성했더니 습관적으로 사용해버렸다. 아마 타입을 지정해주며 Append를 사용했으면 됬을 것 같지만 팀원과 같이 사용하기 위해 편한 .Add(카드)로 변경하였더니 문제가 해결되었다.
다른 문제로는 각각의 해금 데이터를 persistent_data로 저장해주며 플레이어가 임의로 수정한 옵션들을 저장해줄 data로써 역할을 정해놓고 gamesave_data와 분리해서 사용을 시작했는데 해금 데이터를 읽는 과정에서 Watch같은 해금에 영향을 받는 요소들이 데이터가null이므로 false 처리되버리는 현상을 발견하여 해금데이터가 없을때는 원래 데이터가 가지고있는 정보를 그대로 사용하게끔 만들어 문제를 해결하였다.
밑의 영상은 위 문제들을 해결한 영상이며, 추가로 원래 작동했던 {0}과 같은 format 정보들로 교체되는 곳이 오류가 나 이 부분을 수정하려고 한다.
데이터 구조들을 확실히 잡아두는 것은 중요하나 실력이 안될 때는 자신이 할 수 있는 만큼 잡아두고 문제가 터질 때 그 문제들을 해결하며 학습하는 것이 제일 도움이 되는 것 같다.
다양한 문제들을 경험하며 왜 이렇게 사용하면 안되는 지에 대해 경험들이 쌓이며 추후에 접근 방식이 달라지듯 무언가를 안하고 가만히 있는 것보단 행동으로 먼저 진행하고 문제에 봉착해서 경험을 하는 것이 무엇보다 중요하다고 느껴진다.
일단 한 사이클인 게임시작 - 클래스 선택 - 맵진행 - 전투 - 맵진행에서 게임시작 - 클래스 선택 - 맵 진입까지 완료하였다.
여기서 처음 게임을 제작하는 사람들이 있다면 해주고 싶은 말이 있다. 모양새가 어떻든 한 사이클을 먼저 돌려보는 것을 추천한다. 그 전까지의 작업을 할때의 시선과 한번 경험을 해본 후의 시선이 확연히 달라지는 것이 느껴진다. 사이클의 완성 없이 다양한 컨텐츠들을 넣는다면 결국 사이클이 제대로 작동하지 않고 컨텐츠들에 의해 사이클이 가려질 확률이 높아진다. 그 말인 즉슨 게임의 핵심 메커니즘과 자신이 전달하고자 했던 메시지들도 흐려진다는 말이다. 그렇기에 오히려 컨텐츠를 넣을 때는 더 조심스럽게 접근을 하게 될 것 같다.
슬레이 더 스파이어의 맵이 그냥 랜덤하게 각 행마다 최소한으로 생성되어 연결되도록 한 것으로 생각해서 제작해봤으며, 절차적 생성이라고도 하는 정보가 있어서 절차적으로도 구현해 보았다.
절차적 생성이란 데이터를 직접 제작하지 않고 알고리즘을 이용해서 자동으로 생성하는 방법을 말한다.
정의만 봐서는 이해가 잘 되지 않아 만들어보니 무작위성을 이용하여 자동으로 맵을 그려나가는 것으로 이해가 되었지만 실제론 다를 순 있다.
11/20 14:48
절차적 생성만으로 그려보았지만 원하는 모양도 나오지 않고 예외처리를 해서 제작을 하니 더 이상하게 제작이 되어 다양한 자료를 먼저 참고해보려고 커뮤니티 등 여러 곳을 탐색해보니 크게 4가지 자료가 나와 내용들을 종합해보았다.
1. 절차적 생성 + DFS의 결합으로 처음부터 끝까지 진행되는 노드만을 남긴다.
2. 여기서부터는 내 생각이다. 각 노드의 타입을 확률에 맞게 미리 전체 행렬에 절차적으로 생성시킨 후 DFS를 통해 맵을 만든다.
3. DFS를 통해 맵을 먼저 만들어 둔 후 절차적 생성을 통해 각 노드에 타입을 배정한다.
이렇게 크게 3가지를 메인으로 R&D를 진행하고 우리 게임에 제일 어울린다고 판단되는 방식으로 포팅 해볼 생각이다.
어제 다른 부분을 고치느라 맵을 건드리지 못해 오늘 건드리게 되었다.
일단 문제가 생긴 것은 spriteAtlas에서 이미지를 뽑아올때 imageName_0_(clone)같은 접미사들이 계속 붙어서 나오고 주의사항으로 이미지들이 컴프레션 포멧으로 되있다고 주의를 주고있었다.
첫 번째 문제인 접미사들은 밑에 사진과 같이 스프라이트 모드를 Single로 바꿔주고 Apply 해야했다.
두 번째 문제인 컴프레션 포멧 문제는 밑의 사진과 같이 Compression을 None으로 바꿔줬다.
두 문제를 해결한 후 세번째 사진처럼 나오는 것을 확인하였다.
팀원이 보통 UI를 처리해주고 있었기에 오랜만에 건드리려하다 잊어버린 것이 문제였다. 항상 학습을 한 후에 잊지않도록 매번 다른 방식으로 테스트들을 진행해보아야겠다는 생각이 든다.
DFS를 사용하여 마지막 사진으로 만들어 보았다. 작동이 되는 것을 일단 확인했으니 좀 더 잘 만들어 지도록 하며 각각의 노드들에 들어가는 이미지들이 이미지의 확률에 맞게 들어가도록 변경도 해봐야겠다.
지금 보니 드는 생각은 맵의 복잡도가 낮아졌다는 점이다 이 점을 어떻게 보완할지가 문제인데 인접범위를 늘리게되면 복잡도는 늘어나겠지만 노드들이 너무 많이 살아남아서 맵이 난잡해 보일 것 같다.
덱빌딩 로그라이크 장르 게임의 핵심은 결국 전투다. 플레이어는 전장에 놓여진다는 사실 하나만으로도 보유한 카드와 상대 등을 빠르게 파악해야만 한다. 이런 과정을 통해 전황을 본인에게 유리하게 이끌어가는 것. 이야말로 게임 내내 덱을 만들고 카드를 사용하게 되는 코어 루프의 목적일 것이다. 그렇다면 전투를 어떤 모습으로 연출해야 유저로 하여금 더욱 몰입하게 할 수 있을까?
답은 카드에 있다. 결국 우리가 만드려는 게임의 본질은 덱빌딩 로그라이크 게임이므로 카드에 집중할 수 있어야 한다. 이를 위해 배경은 전체적으로 아웃라인이 없고 제한된 색을 사용하는 동시에 어두운(dimmed) 느낌으로 잡았다. 특히 플레이어의 캐릭터나 적 오브젝트가 놓였을 때 구분감이 필요하기 때문에 좋은 선택이라고 본다. 몬스터(크리쳐?)는 일단 임시로 올려 놓았는데 생각보다 잘 어우러지는 느낌이라 다행이다 싶다.
처음에는 시계 컨셉에 맞춰서 디지털 느낌이 나는 카드로 만들어볼까 했다. 다만 만들어놓은 배경의 분위기와는 너무 상반될 거 같아 수십 차례의 수정을 거쳐 아래와 같은 이미지를 만들었다. 임시로 사용할 이미지긴 하지만 잘 어울리니 맘에는 든다. 다음 단계에서는 각 레이어별로 나누어 하나의 스프라이트에 넣은 뒤 유니티에서 불러오는 테스트를 해볼 생각이다.
오늘은 이벤트를 건드려보았다. 일단 전에 작성한대로 잘 진행이 됬으며 한번 나왔던 이벤트가 나오지 않게 저장하는 부분이 초기화가 되는 문제를 확인하고 살펴보니 메인메뉴에서 SaveGame()으로만 처리하고 있어 Load되기전에 초기화가 되기에 나중에 버튼이 나뉘면 되는 것이라 문제가 아니었다.
즉 정상 작동 중이라는 것이다.
이벤트가 처음 시작되기 전 플레이어 데이터에는 지금까지 진행한 이벤트가 있는 지에 대해 알 수 있고 이를 통해 이후 이벤트들을 진행 할 때 같은 이벤트가 나오지 않도록 하여 이벤트가 다양하게 진행되도록 처리를 하였다.
또한 각 이벤트의 선택지가 있고 없고에 따라 동적으로 선택지들을 활성화시켜 없을 시에는 안보이도록 처리를 해뒀다.
먼저 발생했던 문제는 처음 플레이어 데이터가 만들어 졌을 때 전에 돌았던 이벤트 내용이 포함되있던 문제가 있었고 이는 플레이어 데이터가 새로 만들어줄 때 초기화하는 부분이 저장해주는 위치보다 더 뒤에 있어서 생긴 문제이므로 옮겨서 해결하였다.
다음으로 한 개 이상의 이벤트를 진행 후 같은 이벤트로 계속 고정되는 문제도 발생하였는데 이 부분은 이벤트의 저장을 이벤트 진행이 끝난 이후 다음 버튼을 눌렀을 시 저장을 하는데 이벤트가 플레이어 데이터로 들어가기 전에 저장이 끝나버려서 생기는 문제이기에 처음 이벤트로 들어왔을 때 저장해주면서 플레이어 데이터에 현재 진행 중인 이벤트를 따로 변수로 만들어 다시 들어와도 문제가 없게끔 하였고 진행 이후에 같은 이벤트가 나오지 않도록 처리하였다.
업그레이드를 넣을 지 안넣을 지에 대해 아직 회의 중이므로 휴식처에서 회복을 진행하고 바로 다음 씬으로 넘어가게 처리를 해놓았다. 회복과 초과되었을 때도 최대 체력으로 고정되게 끔 조절하였다.
빌드시 보여줄 스플래시 이미지들을 미리 작성하여 보았다. 지금은 원하는 모양이 아니지만 추후 빌드 할 시기에 한번 더 가공을 거칠 예정이다.
오늘은 전투맵에 진입시 랜덤하게 몬스터들이 각 챕터별 임계점에 가깝게 산출되도록 몬스터 뭉치를 만들고 맵에 나올 수 있도록 시스템을 구축해보았다. 현재 슬레이 더 스파이어와 동일하게 체력 한도를 1막 : 48, 2막 : 96, 3막 144로 잡아두고 산출하였다.
첫번째 사진은 각각의 몬스터들이 몇 챕터에 몇 마리씩 분포를 하는 지를 나타내는 몬스터 테이블이다.
이를 통해 체력에 접근하여 각 몬스터별 체력을 합하여 체력한도를 넘지 않도록 조절하였다.
현재 몬스터풀이 0 이되면 안되기에 몬스터들의 분포양을 늘려두었지만 추후 조정을 통해 적은 분포양으로 다양한 몬스터들이 나오도록 준비할 것이다.
두번째 사진은 실제 전투맵에 들어갔을 때 제대로 산출되어 나왔는 가에 대한 결과이다.
정확하게 체력한도를 넘지 않도록 나오는 것을 볼 수 있다.
체력한도를 넘지않도록 계속 몬스터들을 비교할때 현재 몬스터들이 들어있는 리스트내에서 최솟값으로 더해서 계산해주고 있기에 제일 체력이 낮은 "개"가 모두 소진된 상태라면 적이 한마리라도 나올 수 있도록 처리를 해두었다.
R&D를 통해 처음부터 보스 맵까지 이루어진 구조로 작성을 해보았고 완료되었지만 원하는 복잡도의 연결구도가 아니어서 새로 조사를 하던 중 랜덤 워크로 연결을 만들고 이후에 각 계층별로 나누어 보정을 하는 방식을 채택하는 것이 좀 더 좋은 결과가 나올 것이라 판단하여 새로 작성을 시작하였다. 추가로 이벤트를 실제 적용시키기 위해 이벤트 매니저 내에 각각의 현재 이벤트 보상 타입과 보상을 확인하는 메서드를 통해 적용시켜보려고한다.
로우데이터 클래스를 만들때 크게 걱정하지 않은 부분은 오브젝트에 컴포넌트화 되는 스크립트와 연결이 잘 되지 않을까하는 막연한 구조 설계로 인해 현재 데이터 클래스가 있는데도 불구하고 결국 컴포넌트화 되는 스크립트에 동일한 요소를 모두 넣어줘야하는 결과가 발생하였다.
로우 데이터 스크립트에 Monobehaviour를 상속받거나 상속 받고있는 스크립트를 상속 시키게 되면 Dictionary<id,로우데이터>형식으로 제작하고있는 딕셔너리들이 new 되지않아 문제가 생긴다. 이를 해결하기위해 다양한 방법을 시도해 봤지만 결국 그나마 간단하게 해결하는 방법은 컴포넌트화 되는 오브젝트에 new 로우데이터를 만들고 그 lowdata구조의 인스턴스에 딕셔너리에서 id로 찾은 정보들을 연결해 주는 것으로 보인다.
위에 해결방법이라 생각했던 방식을 사용하여 해결이 되었고 원래 방식인 모든 데이터 형식을 눈으로 확인하면서 모두 옮겨 적는 방식보다 안전해졌다고 생각되지만 팀원이 원래 방식이 더 편하다고 느끼면 언제든 바꿀 수 있도록 처리를 해뒀다.