티스토리 뷰
게임의 개발 사항을 정리하는 글이다.
사실, 본인 파트 만 있는 게 아니라, 다른 팀원들의 파트도 섞여 있는 '발표 자료'를 기반으로 작성한 것이긴 하지만, 전체적으로 정리하기는 괜찮다고 판단했다.[사실, 말이 기반으로 작성한 것이지, 복사 + 붙여넣기 이후에 서식 수정이다.]
현재 상황에 맞춰서 어느 정도 편집도 해 놓았으니, 일단 이 글만 보면 기술적인 요소는 모두 파악이 가능할 것이라고 생각한다.

게임 소개
‘모험가’로서 던전을 탐험하는 핵 앤 슬래시 게임입니다.
던전 안에서 아이템을 모아 캐릭터를 강화하고, 강화한 만큼 던전을 강화하여 더 강한 아이템을 모으면서 점점 더 높은 수준의 던전을 재패하는 것이 목적인 게임입니다.
다운로드 URL : https://drive.google.com/drive/folders/1FN6cxYQp_PYpS2U-Uew3MTZUoN-mOQ7u?usp=drive_link
조작법 [PC버전 기준]
- 이동: WASD
- 공격: 마우스 우측 버튼
- 회복: Tab
- 덱 재생: Q
- 상호작용: E
- 카드: 마우스 왼쪽 버튼
스킬 카드 시스템
원하는 카드로 덱을 꾸려 자신만의 전략을 완성하세요.
카드를 강화하여 전략을 강화하세요.

끝 없이 이어지는 던전
랜덤으로 무한히 확장하는 던전에서 끝 없는 질주를!
실패하면 날라가지만, 성공하면 일확천금!

아이템을 장착하여 더욱 강력해지자!
던전에서 구할 수 있는 다양한 아이템들으로 무장하자!
아이템의 특성을 확인하여 더욱 강력한 자신으로!

그리고 더 강해진 던전으로!
던전을 강화해서 더 높은 보상을 노리자!

개발 구조
사용한 기술 스택
게임 엔진
- Unity - 2022.3.17f1
개발 환경
- VisualStudio
- Window 10
협업 도구 & 언어
- Github
- C#
데이터 관리
- Excel
- Json
클라이언트 구조
- GameManager : 전체 매니저 및 데이터 관리
- DataManager : Json파일 연동 관리
- DataContainer: Json 역직렬화 정보 저장용 클래스
- Managers
- UIManager : 전체 UI 관리
- 데이터 매니저들: 각 분야 별 데이터 관리.
- ActionDataManager
- DialogManager
- EventManager
- NPCManager
- ItemDataManager
- MonsterManager
- CardDataManager
- CostEffectDataManager
- BuffManager
- SoundDataManager
- SaveLoadManager : 저장, 불러오기 기능 관리
- SoundManager : 사운드 관련 요소 관리
- Datas
- Inventory
- DungeonInventory : 던전 안에서의 습득물을 임시 보관하는 클래스.
- VillageInventory : 영구적으로 보관하는 품목들을 모아두는 클래스.
- ResultInventory : 던전 탐험의 결과 화면을 구축하기 위한 클래스.
- DungeonInventory의 습득물들을 VillageInventory로 넘겨주는 클래스.
- 던전 탈출 실패 시에는 DungeonInventory의 내용물 일부가 유실된다.
- 단전 탈출 성공 시에는 전 품목이 온전히 넘어간다.
- Deck 관련 Data
- Deck: 현재 착용중인 덱에서 사용할 카드 목록의 정보를 갖는 클래스
- DeckSystem: 플레이 중 사용하는 카드 덱과 관련된 요소를 담당하는 클래스.
- 카드 뽑기, 카드 사용 등
- monsterReinforcement: 던전(몬스터) 강화를 담당하는 클래스.
- EquipSystem : 씬이 넘어갈 때 장비 정보를 보존하기 위한 클래스.
- Inventory
- Parameters
- LastPlayedDungeonLevel: 던전 레벨에 해당.
- 타 기능들 중 던전 레벨에 관련된 요소들의 매개변수로도 쓰인다.
- LastPlayedDungeonLevel: 던전 레벨에 해당.
- DataManager : Json파일 연동 관리
- Character: 플레이어와 몬스터 공통 부모. 캐릭터들의 공통된 요소들의 정리를 담당한다.
- 기본 형태
- CharacterStatus: 캐릭터의 능력치 관련 요소를 담당하는 클래스.
- StateMachine: 캐릭터의 행동 상태 관련 요소를 담당하는 클래스.
- ActionActor: 캐릭터의 공격 액션을 발생시키는 클래스.
- Player: 플레이어 캐릭터 객체 관리
- PlayerAnimationController: 플레이어 캐릭터의 애니메이션관련 요소를 담당하는 클래스.
- PlayerEquipment: 플레이어 캐릭터가 장착한 아이템 관련 요소를 담당하는 클래스.
- PlayerMovement: 플레이어 캐릭터의 이동 관련 요소를 담당하는 클래스.
- PlayerInputManager: 플레이어 캐릭터와 연관된 입력 관련 요소를 담당하는 클래스.
- PlayerStateMachine: 플레이어의 행동을 제어하는 클래스.
- CharacterStateMachine을 상속 받아서 구성.
- AttackParantState와 MoveParentState의 큰 State로 구성한 뒤, 세부 State를 큰 State 내부에서 정의하는 방식으로 구성.
- PlayerStatus: 플레이어의 능력치에 관련된 요소를 담당하는 클래스.
- CharacterStatus를 상속받아서 구성.
- 장비의 능력치나 특성을 적용하는 기능이 포함되어 있다.
- Monster: 몬스터 캐릭터 객체 관리
- MonsterStateMachine : 몬스터의 행동을 제어하는 클래스.
- CharacterStateMachine을 상속 받아서 구성.
- IdleState, ChaseState, KnockbackState, DeathState, EliteAttackState의 다섯 State로 구성
- MonsterStatus: 몬스터의 능력치에 관련된 요소를 담당하는 클래스.
- CharacterStatus를 상속 받아서 구성.
- 엘리트 몬스터의 스테이터스 배율을 적용하는 기능이 포함
- MonsterStateMachine : 몬스터의 행동을 제어하는 클래스.
- 기본 형태
- Item
- 장비
- Weapon : 플레이어의 공격 액션 및 공격력을 형성.
- Amulet : 플레이어의 기본 능력치 형성.
- Trait : Weapon 및 Amulet에 추가로 배정.
- 플레이어 캐릭터의 능력치 상승.
- 특성 개수에 따라 장비 아이템의 등급 결정.
- Card: 카드 덱으로 편성, 인 게임 상에서 스킬으로서 사용될 수 있는 일종의 퀵슬롯 개념.
- 장비
씬 구조
TitleScene

VillageScene

DungeonScene

기술 일람
Excel - Json 데이터 연동
본 프로젝트의 외부 데이터 연동은 DataManager와 DataContainer의 총 2가지의 주체 클래스로 구성됩니다. 이 두 클래스는 DataTypeBase 클래스를 입출력 기반으로 작동하며, 이를 IDataInitializer 인터페이스를 구현하는 클래스가 참조하여 초기화 하는 구조로 이루어져 있습니다.
연동에 사용되는 데이터 파일 양식은 Json으로, 이를 통해서 Excel과 연동하는 구성으로 작업되어 있습니다. 이 기능에 ExcelToJsonWizard 라는 Github 오픈소스 유틸리티를 사용하였으나, 프로젝트 상에서의 Json 입력 기능은 독자적으로 규격화된 입력 체계를 구축하여 사용하였습니다.

또한, 본 프로젝트의 게임 진행 내용 저장 - 불러오기 기능도 Json을 기반으로 작동하도록 구성되어 있으며, 세이브 데이터의 저장 위치를 Appliction.persistentDataPath를 이용, 파일의 위치에 관계 없이 동일한 경로를 사용할 수 있도록 구성하였습니다.
다만, 이 기능은 Excel과의 연동이 필요하지 않기 때문에 ExcelToJsonWizard를 활용하지 않고, 저장할 데이터를 구조체로 묶은 이후, 이 내용을 저장하는 방식으로 구성되어 있습니다.
Action System
본 게임은 ActionContainer와 ActionObject 2개의 프리팹을 이용하는 동시에, 액션의 각 형태를 모듈로 구성하여 다종다양한 액션을 통일된 Data 양식을 통해서 형성될 수 있도록 구성되어 있습니다.
이를 통하여 ObjectPool에 사용하지 않는 오브젝트들이 상주해 있는 상태를 예방하고, 더욱 나아가서 엑셀 만으로도 액션을 형성할 수 있도록 구성하였습니다.

개선 가능한 점
현재 오브젝트의 형상은 애니메이션이 아닌 스프라이트로 조절되고 있고, 액션 오브젝트의 움직임이 애니메이션으로 조절되고 있습니다.
다만, ‘애니메이션으로 구성된 FX’를 사용하기 위해서는 현재로서는 움직임을 표현하기 위한 에니메이션을 형상을 나타내는 용도로 사용해야 하는 상황입니다.
비록 기초적인 움직임 4가지는 애니메이션이 아닌 스크립트로 제어되는 덕분에 작동에 문제가 발생하지는 않았지만, 오브젝트의 형상도 애니메이션으로 제어했다면 더욱 폭 넓은 액션 구성이 가능했을 것입니다.
컴포넌트 기반 Object Pool
GameObject가 아닌, ObjectPoolContent 클래스를 상속받는 **‘컴포넌트’**를 이용해서 작동하는 Object Pool입니다.
기존의 GameObject를 활용하는 방식은 별 다른 처리 없이 다양한 내용을 담을 수는 있었지만 사용할 때 마다 GetComponent를 이용해서 사용할 컴포넌트를 가져와햐 한다는 단점이 있었습니다.
이에 이 GetComponent를 줄여서 최적화 수준을 높이기 위해서 ObjectPoolContent라는 기본적인 오브젝트 풀을 활용하기 위한 기능들을 정리해 놓은 부모 클래스를 작성한 다음, 이 ObjectPoolContent를 상속받아서 구성된 각 컴포넌트를 기반으로 작동하도록 구성하였습니다.
- ObjectPoolContent 코드 스크린샷

- ObjectPoolList 코드 스크린샷
- 생성자
- Get
- Release
- 생성자
절차적 던전 확장 알고리즘
플레이어의 위치를 기반으로 새로운 방에 진입할 경우, 각 방향 별 통로 현황을 확인하고, 통로가 열려있다면 그 방향에 새로운 방을 생성하는 구조를 사용하였습니다.
이에 더해서 방이 생성될 때, 생성된 방을 기준으로 4개 변의 통로가 이미 있는지를 파악하여 없는 위치의 통로를 생성하도록 구성하여, 이러한 구조가 순환할 수 있도록 구성하였습니다.
동시에 통로는 정해진 확률(현재는 35%)으로 ‘닫힌 상태’로 생성되도록 하여 던전 구성이 마냥 확장 만 되는 것이 아닌, 다양한 패턴이 나올 수 있도록 구성하였습니다.

단, 시작한 지 얼마 안되었을 때에 닫혀있는 통로가 너무 많이 나오는 탓에 막혀버리는 경우도 있어서 초반 한정으로 일정 이상의 통로가 열려있도록 로직을 추가, 유의미 한 통로의 수를 확보할 수 있도록 구성하였습니다.
개선 가능한 점
현재 바닥과 벽이 매 필드 확장 때 마다 생성되고 있는 구조로 구성되어 있습니다.
다만, 이 바닥과 벽은 실제로는 방의 종류에 관계 없이 공통으로 활용되는 요소이기 때문에, 이 둘을 ‘방’에 엮어서 프리팹으로 같이 구성하는 게 아니라 플레이어를 따라서 같이 이동하는 요소로서 구성하고, 방 프리팹 자체는 방해물 만으로 구성했었다면 현재 보다 최적화 상으로 더욱 충실했을 것이라 생각합니다.
PathFinding - NavMesh+
본 작품은 방과 방 사이에 벽이 있는 구조로 되어있습니다. 동시에 필드 안에서도 다종다양한 이동 방해 요소들이 존재합니다.
이에 본 작품의 몬스터들은 선형으로 추적하는 알고리즘이 아닌, 장해물의 배치를 인식하고, 그에 맞춰서 이동 경로를 최적화 할 수 있어야 했습니다.
이 ‘길찾기 기능’ 자체는 AI Navigation 패키지로 유니티가 기본적으로 제공하는 기능 중 하나로 이미 있었고, 해당 기능을 사용하면 시각적으로 알고리즘 기반 구성, 특히 ‘동적 NavMesh Bake’의 결과를 확인할 수 있기 때문에, 전체적인 디버깅이나 코드 결과 분석에 용이하다고 판단하였습니다. 다만, AI Navigator는 3D 환경을 상정하고 제작된 패키지라서 2D 환경에서는 기본적으로는 활용하기 어려웠습니다. 이에 AI Navigation을 2D 환경에서도 사용할 수 있게 해 주는 NavMesh+ 패키지를 통하여 구현하였습니다.
또한, 본 작품은 상술한 ‘절차적 던전 확장 알고리즘’에 의해서 지속적으로 필드가 확장되는 구조이기 때문에 런타임 안에서 필드가 확장될 때에 맞춰서 동적으로 Bake되도록 구성, 새로 만들어진 필드에도 정상적으로 AI Navigation이 적용되도록 구성하였습니다.
다만, 이렇게 구성할 경우 ‘동적 Bake 시의 필드의 크기’가 최적화에 직격타를 끼치기 때문에, 플레이어의 위치의 상하좌우 + 대각선 1칸 이내의 필드만 활성화되도록 구성하였습니다.

인벤토리 - 재활용 스크롤 뷰
본 작품의 장르가 ‘핵 앤 슬래쉬’인 만큼, 본 작품의 아이템 드롭 빈도와 개수가 상당히 많은 편입니다.
이로 인해서 만약에 인벤토리에서 이 모은 아이템 항목들 마다 UI를 새로 생성하도록 구성한다면 소유 아이템 수가 3자리를 넘볼 수도 있는 본 게임에서 인벤토리 UI를 형성하는 시스템 부하가 어마어마하게 높아질 것이며, 동시에 이 모든 UI의 위치를 변경해야 하는 스크롤 자체의 부하도 유의미하게 증가할 것으로 판단하였습니다.
그래서 생각한 방법이 **‘표시되는 영역 안의 아이템 만 표시하고, 안보일 때에는 다음 아이템을 표시하는 데에 재활용하자’**였습니다.
재활용 스크롤 뷰는 다음 방식으로 구현되어 있습니다.
- 기본적으로 화면에 표시되는 UI 수 + 여유분 만큼의 오브젝트를 미리 UI 프리팹에 넣어둡니다.
- 해당 UI가 활성화 되었다면, 순번 0 부터 표시하도록 내부 UI를 갱신합니다.
- 이후, 스크롤에 따라서 내부 컨텐츠 내용을 갱신합니다.

Finite State Machine
본 프로젝트의 플레이어 및 몬스터의 행동 제어는 FSM을 통하여 작동하도록 구성되어 있습니다.
단, 플레이어와 몬스터의 행동 범위가 다른 탓에, 구조가 다소 다르게 구성되어 있습니다.
플레이어
유한상태머신은 캐릭터나 객체의 행동과 상태를 체계적으로 관리하기 위한 방법입니다.
게임에서 캐릭터들은 어떠한 '상태' 를 가지게 됩니다. 예를 들어, "대기", "이동", "공격", "피격"과 같은 것들입니다. 이런 상태에 놓여있을 때의 캐릭터의 행동을 한 번에 정의하려 한다면 어려움을 겪을 수 있습니다. 그래서 각 상태마다 행동 원리를 다르게 기술하면 행동을 정의하기 편하고 좀 더 엄밀하게 캐릭터를 관리할 수 있게 됩니다.
하지만 유한상태머신에도 약점이 있습니다. 캐릭터의 상태가 너무 많아지게 된다면 오히려 행동을 정의하기 복잡해진다는 것입니다.
예를 들어 캐릭터의 상태가 "대기"와 "이동"만 있을 때에는 서로 상태를 이동할 때 두 종류의 코드만 작성하면 됩니다. 하지만 상태가 세 개면 여섯 종류, 네 개면 열두 종류, 다섯 개면 스무 종류로 점점 기술해야 할 상태 이동의 코드가 점점 많아지게 됩니다. 이러면 오히려 쉽게 작성하려고 시작한 유한상태머신이 더 어려워지게 됩니다.
그래서 이 부분을 보완하기 위해 항목별로 구분해 "이동"의 항목에는 걷기와 넉백 등이 있고, "공격"의 항목에는 일반 공격과 차지 공격이 있는 식으로 개선했습니다. 이렇게 하면 상태가 많아져도 효과적으로 항목을 나누어 기술할 수 있고, 상태의 흐름도 좀 더 명확히 확인할 수 있게 됩니다.

몬스터
몬스터는 현재 6개의 스테이트간의 흐름을 통해서 행동을 제어하고 있습니다.
이러한 구성을 통해서 각 스테이트의 독립성을 형성, 수정이 용이하도록 구성하였습니다.

트러블 슈팅
ActionSystem 최적화 이슈
액션 오브젝트 다량 생성 시 프레임 드랍 문제
- 문제 제기
- 액션 시스템의 초안을 사용하고 있었을 때, 공격 오브젝트가 10개 남짓 만 발생하였음에도 급격한 프레임 드랍이 발생하는 문제가 발생한 바 있습니다.
- 비록, 유니티 에디터가 실 환경 보다 프레임드랍에 취약하다고는 하나, 이 정도의 수에 프레임 드랍이 발생하는 것은 문제가 크다고 판단하여 수정을 진행하였습니다.
- 문제 파악
- 액션 시스템의 초안에서는 하나의 Container가 다수의 Object를 지니고, 하나의 Object가 다수의 Effecter를 가지는 구성으로 되어 있어, 액션을 한 번 사용하면 가비지가 2자릿수로 쌓이는 편이었습니다.
- 추가로, 이 시기의 오브젝트 풀은 GameObject로 동작하고 있었기 때문에 GetComponent로 인한 시스템 부하도 무시할 수 없었습니다.
- 문제 해결
- 그렇기에, ActionSystem을 재구성 하여 ActionEffector를 같은 액션 안에서는 공유할 수 있는 모듈으로 만들어서 상술한 수직 구조로 인한 가비지 증식을 예방하였습니다.
- 동시에 Object Pool을 컴포넌트 기준으로 바꿈으로써 동적으로 GetComponent를 하는 횟수를 줄여서 이로 인한 부하도 줄였습니다.
- 그 결과, 현재 백여개의 오브젝트가 발생해도 약소한 프레임 드랍으로 그치는 형식으로 최적화가 정돈되었습니다.
절차적 필드 확장 로직 최적화 이슈
몬스터의 중앙집결 문제
- 문제 제기
- 최초 절차적 필드 확장 메커니즘을 작성하였을 때, 생성된 몬스터가 모두 좌표 상 원점(0, 0)에서 발생하게 되는 문제가 발생했었습니다.
- 여기에 더해서 플레이어가 인식 범위 안으로 들어가도 몬스터들이 그대로 멈춰있는 문제도 함께 발생했었습니다.
- 문제 파악
- NavMesh를 동적으로 Bake 할 때, Bake 되는 동안 NavMesh가 소멸하는 것으로 가정, 그로 인해서 NavMesh를 형성하는 오브젝트의 위치인 (0, 0)으로 이동한다고 가정, 몇 가지 테스트를 해 보았습니다.
- NavMeshAgent를 비활성화 하고 생성 → 목표 위치에 정상적으로 출현.
- NavMeshAgent를 비활성화 한 상태에서 생성 후 활성화 → (0, 0)에서 출현.
-
NavMesh를 미리 Bake한 지역 한정으로만 생성 → 목표 위치에 정상적으로 출현.
- 그 결과,가정이 옳다는 것으로 판단, 이에 따른 수정을 진행하였습니다.
- NavMesh를 동적으로 Bake 할 때, Bake 되는 동안 NavMesh가 소멸하는 것으로 가정, 그로 인해서 NavMesh를 형성하는 오브젝트의 위치인 (0, 0)으로 이동한다고 가정, 몇 가지 테스트를 해 보았습니다.
- 문제 해결
- NavMesh를 Bake 하는 동안 전체 몬스터의 NavMeshAgent를 비활성화 하고, NavMesh가 Bake 된 이후 다시 활성화 하도록 수정하여 본 문제를 해결하였습니다.
몬스터의 순간이동 문제
- 문제 제기
- 위 사항을 적용하고 나서 몬스터가 중앙에서 발생하는 경우는 없어졌지만, 이번에는 몬스터가 간헐적으로 이상한 위치로 순간이동하는 문제가 발생했습니다.
- 이 문제는 ‘필드를 더 많이 확장할 수록’ 발생 빈도가 눈에 띄게 올라가는 편이었고, 순간이동 한 몬스터는 완전히 다른 방에서 출현하거나, 플레이어 위치에서 갑자기 생성되거나 특정한 방에 모여있었습니다.
- 문제 파악
- 이번에는 해당 문제를 NavMeshAgent가 활성화되기 전에 NavMesh의 동적 Bake가 종료되지 않아서 발생한다고 가정하였고, 이에 따라서 아래 해결 방법을 구성하였습니다.
- 문제 해결
- 플레이어에게서 멀리 위치한 방은 비활성화 되는 것에 더해서 NavigationModifier 컴포넌트의 IgnoreFromBuild를 활성화 하고, 가까이 위치한 방은 활성화 되는 것에 더해서 IgnoreFromBuild를 비활성화 하도록 수정하였습니다.
- 그 결과, 방을 넘어갈 때 발생하던 프레임 드랍이 크게 줄어듦과 동시에 해당 문제의 발생 비율이 현격히 줄어, 현재는 테스트로는 찾아볼 수 없는 정도 까지 낮아졌습니다.
세이브 데이터 오작동 이슈
Application.persistentDataPath 접근 권한 문제
- 문제 제기
- 세이브 데이터를 저장할 때, Application.persistentDataPath / Save/SaveData#.json [#: 세이브 슬롯 숫자] 경로를 사용했는데, 분명 데이터 파일 저장을 위한 경로임에도 ‘접근 권한’으로 인하여 작동이 되지 않고 있었습니다.
- 문제 파악
- 검색 결과, 원래라면 접근 권한에 대한 오류가 나지 않는 내용인 것을 확인, 이에 따라서 ‘오류의 원인은 접근 권한이 아니다’라고 가정하여, 그 이후 생각할 수 있는 해결법을 순차적으로 적용해 나갔습니다.
- 문제 해결
- 제일 처음 시도했던 것은 ‘파일을 미리 만들어 둔 뒤에 작업하기’였습니다.
- File.Create(경로 + 파일명)으로 파일을 생성한 뒤에 WriteAllText()를 이용해서 편집 해 봤으나, 이미 열려있는 파일이라 닫아야 한다는 경고문이 출력되었습니다.
- 그 다음에 시도한 것은 디렉토리 만 먼저 만든 뒤 작업하기 였습니다.
- Directory.CreateDirectory(경로)로 목표 경로를 생성한 뒤에 WirteAllText()를 이용해서 편집을 해 보았습니다.
- 이후 개인적인 실수로 인해서 몇 번의 오작동이 있긴 했으나, ‘세이브 파일 저장 및 불러오기’ 만큼은 정상적으로 동작하였습니다.
- 제일 처음 시도했던 것은 ‘파일을 미리 만들어 둔 뒤에 작업하기’였습니다.
화면 비율이 변하면 UI의 배치가 어그러지는 이슈
화면 비율이 변하면 Screen이 오작동하는 문제
- 문제 제기
- 모바일 버전을 작업하면서 UI 등의 표시가 비정상적으로 작용하는 문제가 발생, 이로 인해서 정상적인 플레이가 불가능한 문제가 발생했습니다.
- 비단 모바일 버전 뿐만이 아니라, 화면비가 16:9가 아닌 PC버전에서도 동일 문제점이 발생하는 점을 확인하였습니다.
- 문제 파악
- 1920 * 1080 해상도 플레이 할 때에는 어그러지는 점이 없었지만, 화면 비가 다른 환경에서는 문제가 발생하지 않는다는 점으로 미루어, 화면 비율이 바뀌면 원래 설정해둔 비율이나 위치 등이 정상 작동하지 않는다고 추정, 확인하여 수정 작업을 진행하였습니다.
- 문제 해결
- 화면 비율 내에서 짧은 부분에 맞게 해서 16 : 9 비율을 강제로 맞춘 뒤, 화면 밖에는 레터박스가 형성되도록 수정하였습니다.
- 추가로, UI나 기타 문제가 발생하던 요소들의 위치 계산을 화면에 따른 비율 계산으로 통일시켜, 상기 문제를 해결하였습니다.
마우스의 클릭 위치가 해상도에 따라 다르게 적용되던 문제
- 문제 제기
- 카드 덱 구성 UI에서 카드를 드래그할 때, 화면 해상도에 따라서 드래그 되는 위치가 달라지는 것을 확인하였습니다. 추가로, 카드의 크기도 Scale이 (1, 1, 1)으로, 기존과 동일함에도 어마어마하게 커지는 것을 확인하였습니다.
- 문제 파악
- 위치 구성 코드를 확인 한 결과, transform.position 조정으로 이동하고 있어, 이로 인해서 z값이 0이 되어 카드 UI가 어마어마하게 커지는 것이라는 점을 확인했습니다.
- 추가로, 화면 비에 따른 UI의 절대 좌표 변화에 대응하는 코드가 없어, 화면 비에 따른 마우스의 이동 값 차이가 그대로 카드 UI의 위치 변화에 적용되고 있다는 것을 확인하였습니다.
- 문제 해결
- transform.position이 아닌, rectTransform.anchoredPosition을 기반으로 위치가 변화하도록 수정하였습니다. 이에 따라서 카드 UI의 크기가 커지는 현상이 수정되었습니다.
- RectTransformUtility 라이브러리의 ScreenPointToLocalPointInRectangle 메서드를 이용, 화면 상에서의 마우스 좌표가 아닌, UI 내부에서의 마우스의 좌표 이동을 이동 기준으로 사용하도록 수정하였습니다. 이에 따라서 카드 UI의 위치가 해상도에 따라서 크게 어그러지는 현상이 해결되었습니다.
유저 테스트 결과
유저 테스트 통계
- 유저 설문 기간: 2024.01.11 ~ 2024.01.15 18:00
- 중점 사항
- 덱 시스템의 사용자 평가
- 최적화 체감 평가
- 조작감 사용자 평가
유저 평점

플레이 타임 추이

덱 빌딩 시스템 만족도

주요 의견
- 카드가 계속해서 쌓이는 구조인데 한 번에 정리할 수 있는 기능이 없다
→ 카드 일괄 판매 기능 추가 패치 진행. - ‘마우스 클릭 및 드래그’ 조작이라 조작에 번거로움이 있었다.
→ 게임의 기반 컨셉이라 대응 불가능.
→ 대신 카드에 대한 상향을 진행하여 번거로움에 대한 보상을 늘리는 방향으로 수정.
최적화 평가

주요 의견
- 렉 없이 원활히 진행되었다.
- 2D인 점을 고려해도 매우 쾌적한 플레이가 가능했다.
※ 2점의 경우, ‘최적화를 어떻게 하는 것인지 설명이 필요하다’는 내용이었습니다.
조작감 평가

주요 의견
- 공격할 떄 마다 살짝 멈추는 느낌이 있었다.
→ 버그로 판명. 수정 패치 진행. [패치 노트에는 내용 없음.]
※ 전체적으로 위 내용이 대부분이었습니다.
버전 별 업데이트 내역
UT 1.0
유저 테스트 개시, 설문조사 시작.
UT 1.1
- 보패에 개별 이미지를 적용하였습니다.
- 보패 일괄 판매 기능을 추가하였습니다.
- 던전 강화 시스템을 재조정하였습니다.
- 아이템 레벨 기능을 추가하였습니다.
- 전체적인 밸런스를 재구성하였습니다.
- 몇 가지 버그를 수정하였습니다.
UT 1.2
- 덱 빌드 UI 및 카드 강화 UI에 카드 별 랭크 표시를 추가하였습니다.
- 카드 강화 UI의 카드에 현재 장착 여부 표시를 추가하였습니다.
- 이제 더 이상 장착 중인 카드 덱은 삭제가 불가능합니다.
- 이제 뽑을 카드 덱에 카드가 없다면 카드 게이지가 표시되지 않습니다.
- 이제 덱 빌드 UI에서 현재 덱 내용에 있는 카드의 Data 버튼을 이용해 정보를 열람해도 오류가 나지 않고 정상적으로 정보가 표시됩니다.
- 카드 일괄 판매 기능이 추가되었습니다.
UT 1.2.1
- 기존의 망가졌던 세이브파일을 호환할 수 있도록 하는 기능을 추가하였습니다. [※ 착용 덱이 첫번째 덱으로 초기화됩니다. 주의 부탁드립니다.]
- 해상도에 따라서 UI의 크기가 화면과 맞지 않았던 문제를 해결하였습니다.
- UI와 관련된 버그를 다수 수정하였습니다.
- 모바일 버전을 추가하였습니다.
- 게임 아이콘을 수정하였습니다.
UT 1.2.2
유저 테스트 종료, 설문 조사 마감.
- 던전에 들어가거나 나갈 때, 카드 덱의 초기화가 비 정상적으로 진행되는 현상을 수정하였습니다.
- 저장된 파일을 불러올 때, 장비 중인 아이템을 추가 습득하는 버그를 수정하였습니다.
- 던전에서 사망 시 드물게 아이템을 중복 습득하던 버그를 수정하였습니다.
- 던전에서 몬스터가 드물게 아이템을 여러 번 드롭하던 버그를 수정하였습니다.
- 벽이나 탄환이 UI를 가리는 버그를 수정하였습니다.
- 이따금씩 벽의 표시 상태가 이상해지는 버그를 수정하였습니다.
실제 출시 준비, 유저 테스트 버전 종료.
- 갤럭시 S 24 등의 최신형 기기에 대한 호환성 패치를 적용하였습니다.
- 모바일 버전에서 키보드 + 마우스용 컨트롤 키 안내 문구가 보이지 않도록 수정하였습니다.
'스파르타 내일배움캠프 > 최종 프로젝트 리포트' 카테고리의 다른 글
최종 프로젝트 리포트 - 10 [기획 최종 정리] (1) | 2025.01.23 |
---|---|
최종 프로젝트 리포트 - 9 [최종 발표회] (0) | 2025.01.22 |
최종 프로젝트 리포트 - 8 [빌드 - 유저 테스트 시작] (0) | 2025.01.13 |
최종 프로젝트 리포트 - 7 [세이브 - 로드 시스템] (0) | 2025.01.09 |
최종 프로젝트 리포트 -6 [절차적 생성을 이용한 필드 무한 확장] (1) | 2025.01.09 |