유니티 RPG - 57. 포트폴리오
프로젝트 개요
- 게임개요
- 1인 개발 프로젝트
- 개발기간 : 2024.10.13 ~ (실제개발 약 3개월)
- 장르 : 백뷰 형식 3D RPG
- Github 주소
- 기술스택
- Unity 2021 LTS
- C#, JSON
- 프로젝트 주요 목표
- RPG 게임의 핵심 기능 구현(재미, 게임성 고려X)
- 최적화된 클라이언트 시스템 설계
- 유지보수와 확장성을 고려한 객체지향적 설계
- 짧은 플레이 영상
게임 플레이
게임 플로우는 다음과 같습니다.
- PersistentScene
PersistentScene에는 “게임 전반에 걸쳐 유지되어야하는 오브젝트들”이 존재합니다.
이 씬은 게임을 플레이하는동안에 Unload 되지않으며, 다른 씬들을 Additive 모드로 로드하여 이 씬에 존재하는 객체들에 접근할 수 있도록 하였습니다.
플레이어, 카메라, 여러 UI와 매니저 클래스들이 해당되며, 초기화작업을 거친뒤 ViliageScene를 로드합니다.
- ViliageScene
ViliageScene은 플레이어가 게임을 시작할 때 보게되는 가장 첫 씬입니다.
상점 NPC가 존재하며, 전투에 필요한 여러 아이템을 구매할 수 있습니다.
포탈을 통해 던전에 입장할 수 있습니다.
- LoadingScene
LoadingScene은 플레이어가 다른맵으로 이동할 때 다음 씬이 로드되는동안 보여지는 로딩씬입니다.
현재 로딩상태를 보여주는 로딩바와, 게임팁을 출력합니다.
- DungeonScene
DungeonScene은 플레이어가 몬스터와의 전투가 이루어지는 공간입니다.
잡몹을 모두 처치하면 컷씬과 함께 보스몬스터가 소환되며, 모든 몬스터를 처치하게되면 보상과함께 마을로 돌아갈 수 있는 포탈이 생성됩니다.
주요 시스템
프로젝트에서 구현한 주요 시스템은 다음과같습니다.
- 인벤토리
- 아이템 설계
- 퀵슬롯(인벤토리 연계)
- 캐릭터 정보창(인벤토리 연계)
- 전투 시스템
- 몬스터 AI
- 플레이어
- 데이터 관리
- JSON 데이터 Load & Save
- 플레이어, 아이템, 인벤토리 등의 데이터 관리
- 기타
- UI
- 게임의 성능 향상을 위한 최적화
- 여러가지 매니저 클래스
인벤토리
인벤토리 시스템의 구조는 다음과 같습니다.
- Inventory : 인벤토리내의 아이템 데이터를 관리하고, 인벤토리의 실질적인 동작을 처리합니다.
- 인벤토리 데이터 파일(JSON) Load & Save
- 아이템의 추가(습득), 스왑, 사용, 제거 등
- Code
- InventoryUI : 인벤토리내의 마우스 이벤트와 모든 아이템 슬롯을 관리합니다.
- 인벤토리의 아이템 슬롯을 배치 및 생성합니다.
- 마우스 클릭, 드래그 앤 드롭을 구현하여 인벤토리내 UI와 상호작용할 수 있도록 했습니다.
- 인벤토리의 아이템 슬롯 정보들을 리스트로 관리합니다.
- Code
- ItemSlotUI : 각 아이템 슬롯의 데이터를 관리하고, 슬롯에서 발생하는 기능들을 구현합니다.
- 슬롯의 인덱스, 아이템 이미지, 아이템 텍스트 등의 데이터
- 아이템 이미지의 표시, 강조효과 등의 기능 구현
- 이미지는 ResourceManager를 통해 Addressable 에셋을 Load하여 표시
- Code
인벤토리 시스템은 크게 위 3가지로 구성되어있습니다.
ItemSlotUI는 InventoryUI가 관리하며, Inventory는 InventoryUI와 상호작용합니다.
실제 아이템 객체 Item은 Inventory가 관리하고 있기때문에 ItemSlotUI의 Item 상태 공유는 InventoryUI, Inventory에 의해 간접적으로 이루어집니다.
즉, 인벤토리내에서 이벤트(새로운 아이템이 추가되는등의)가 발생하면 InventoryUI를 참조해 UI를 갱신하고
UI에서 사용자 이벤트가 발생했을 때는 InventoryUI가 Inventory를 참조하여 아이템 또는 아이템배열을 갱신합니다.
인벤토리 주요 기능은 다음과 같습니다.
- 아이템 추가
- 상점에서 아이템을 구매하는 등의 이벤트가 발생하면 아이템추가 메서드가 호출됩니다.
- 아이템이 추가될 때 인벤토리내 앞쪽부터 빈자리를 찾아 추가합니다.
- 동일한 아이템(Countable)이 추가될경우 가장앞쪽의 동일 아이템과 갯수가 합쳐집니다.
- 아이템 제거
- 아이템을 버리거나, 모두 사용했을때 아이템제거 메서드가 호출됩니다.
- 아이템의 이미지와 텍스트, 배열에 저장된 아이템 데이터를 비웁니다.
- 아이템 스왑
- 마우스 드래그앤드롭으로 두 아이템의 위치를 바꿉니다.
- 이때 동일한 아이템(Countable)은 갯수가 합쳐질 수 있습니다.
- 아이템 사용
- 마우스 우클릭을 통해 아이템을 사용할 수 있습니다.
- 장비아이템은 장착되고, 물약아이템은 사용됩니다.
아이템
RPG에서 아이템의 종류는 매우 다양하고, 아이템 마다의 특징이 존재합니다.
따라서 아이템을 설계할 때 쉽게 새로운 종류의 아이템을 추가하고 관리할 수 있도록
유지보수성과 확장을 고려한 객체지향적 아이템 구조를 설계하였습니다.
- 아이템의 데이터를 공통적인 부분은 묶고, 세부적인 부분은 분리하여 상속을 통해 새로운 아이템 추가가 쉽도록 하였습니다.
- ex. 포션아이템
- Id, Name 등은 ItemData에 작성
- 아이템 수량(Amount) 등은 CountableItemData에 작성
- 회복량 등은 PortionItemData에 작성
- ex. 포션아이템
- 또한 데이터 부분과 기능 부분을 분리하여 유지보수가 쉽도록 하였습니다.
- ItemData 계층은 데이터 구조
- Item 계층은 게임 내 동작(로직)
프로젝트에서는 크게 두가지 종류의 아이템을 구현하였습니다.
- 장비아이템(EquipmentItem)
- 장비아이템은 슬롯 한칸에 하나의 아이템만 존재할 수 있습니다.
- 장비아이템에는 세부적으로 무기와 방어구 아이템이 있습니다.
- “IEquipableItem” 인터페이스 상속으로 아이템의 장착/해제를 구현합니다.
- 수량이 있는 아이템(CountableItem)
- 수량이 있는 아이템은 슬롯 한칸에 여러개의 아이템이 존재할 수 있습니다.
- 수량이 있는 아이템은 몬스터의 전리품, 물약, 주문서 등이 있습니다.
- 수량이 있는 아이템중에서도 사용이 가능한 아이템은 “IUsableItem” 인터페이스 상속으로 사용이 가능한 아이템(PortionItem)을 구현하였습니다.
아이템 생성의 전체적인 흐름은 다음과 같습니다.
-
JSON 파일로 작성되어있는 데이터를 “DataManager“가 Load 합니다.
-
DTO 클래스는 JSON 데이터를 직/역직렬화할 때 사용됩니다.
- DataManager는 각 DTO로 ItemData 를 생성하고, 딕셔너리에 캐싱해둡니다.
- 이후 추가적인 로딩없이 재사용할 수 있고, 게임 전역에서 데이터를 쉽게 참조할 수 있도록 하였습니다.
- 아이템이 생성되어야할 때, 캐싱되어있는 데이터를 가지고 아이템을 생성합니다.
이러한 설계방식을 통해 유지보수가 쉽고, 확장성이 높은 객체 지향 기반의 아이템 시스템을 구현하였습니다.
퀵슬롯
퀵슬롯은 인벤토리에서 드래그앤드롭을 통해 아이템을 등록하고 빠르게 사용할 수 있도록하는 UI입니다.
-
물약아이템만 등록이 가능합니다.
-
숫자키 (1,2,3,4) 입력을 통해 아이템을 사용할 수 있습니다.
- PlayerItemGroupUI : 모든 퀵 슬롯 데이터를 관리합니다.
- Inventory와 상호작용하며 아이템 등록, 사용, 제거를 수행합니다.
- 키 입력을 처리합니다.
- PlayerItemSlotUI : 각 슬롯의 데이터를 관리합니다.
- 슬롯에 등록된 아이템의 이미지와 텍스트를 표시하고 제거합니다.
- 슬롯에 등록된 아이템의 사용을 요청합니다.
퀵 슬롯에 아이템을 등록하고 사용하는 과정은 다음과 같습니다.
-
InventoryUI에서 마우스 이벤트(퀵슬롯에 아이템 등록)가 발생하여 Inventory에 이벤트 처리를 요청합니다.
-
Inventory에서 PlayerItemGroupUI에 등록하려는 아이템 데이터를 공유합니다.
-
넘겨받은 데이터로 PlayerItemSlotUI에 아이템 등록을 요청합니다.
-
아이템 아이콘 및 텍스트를 표시합니다.
-
입력이 발생하면 해당 슬롯에 아이템 사용을 요청하고, 슬롯에서 Inventory에 아이템의 사용을 요청합니다.
-
만약 아이템 사용이벤트가 발생하면 인벤토리와 퀵슬롯의 아이템상태를 갱신합니다
캐릭터정보창
캐릭터 정보창은 플레이어가 장착한 장비와 현재 능력치를 확인할 수 있는 UI 입니다.
- UI의 왼쪽부분은 플레이어가 장착한 장비슬롯이 있습니다.
- 슬롯에 커서를 올리면 강조효과 + 아이템 툴팁이 출력됩니다.
- 슬롯을 우클릭하면 장착중이던 장비를 해제할 수 있습니다.
- UI의 오른쪽부분은 플레이어의 능력치가 표시됩니다.
- 현재체력, 공격력, 방어력 등의 능력치가 표시되며 장비 및 스킬로 인한 증가치가 합산되어 표시됩니다.
캐릭터 정보창은 인벤토리 코드를 재사용하여 구현하였습니다.
- EquipmentUI : 장비슬롯의 데이터들을 관리하고, 마우스이벤트를 구현합니다.
- Inventory 와 상호작용하며, 장비 슬롯에 아이템을 등록 및 제거합니다.
- 장비 장착등의 이벤트가 발생하면 현재 상태를 저장합니다.
- EquipmentSlotUI : 각 장비슬롯의 데이터를 관리하고, 슬롯에서 발생하는 기능을 구현합니다.
- 슬롯의 인덱스, 아이템 이미지등의 데이터
- 아이템 이미지의 표시, 강조효과 등의 기능 구현
- 이미지는 ResourceManager를 통해 Addressable 에셋을 Load하여 표시
캐릭터 정보창에 아이템을 등록하는 과정은 다음과 같습니다.
-
InventoryUI에서 마우스 이벤트(장비아이템 사용)가 발생하여 Inventory에 이벤트 처리를 요청합니다.
- Inventory에서 아이템 사용을 처리하고, EquipmentUI에 장착한 아이템 데이터를 넘겨줍니다.
- 장비 아이템 장착에 따른 능력치 처리는 아이템 객체의 Equip(), UnEquip() 에서 처리합니다.
-
넘겨받은 데이터로 슬롯에 아이템데이터를 저장하고, EquipmentSlotUI에서 아이템 이미지를 등록합니다.
- 반대로 장비의 해제는 EquipmentUI에서 마우스 이벤트를 처리하고, Inventory에 후처리를 요청합니다.
- 해제한 아이템은 인벤토리에 추가됩니다.
전투 시스템
전투 시스템은 크게 플레이어와 몬스터 부분으로 나뉩니다.
- 플레이어
- 플레이어 무기 시스템
- 플레이어 스킬 시스템
- 몬스터
- 몬스터 AI
플레이어
플레이어 기본 조작은 다음과 같습니다.
- 플레이어는 키보드 방향키로 움직일 수 있습니다.
- 플레이어는 ‘C’ 키 입력으로 기본 공격을 할 수 있습니다.
- 플레이어는 ‘A’, ‘S’, ‘D’ 키 입력으로 스킬 공격을 할 수 있습니다
플레이어는 현재 장착중인 무기에따라 무기 프리팹을 생성하여 손에 들고있도록 하였습니다.
무기의 타입은 다음과 같습니다.
- None : 무기를 장착하고 있지 않음.
- 무기를 장착하고 있지 않을때는 주먹공격을 수행
- Sword
- Staff
- Bow : 공격은 현재 미구현
무기의 실제 공격판정은 두가지 방식으로 구현하였습니다.
- Raycast
- Collider
검 공격과 같이 몬스터와 직접 부딪힐 때 공격판정을 발생시킬때는 Collider 방식으로 구현하였습니다.
무기의 설계 방식은 다음과 같습니다.
- Weapon 클래스는 모든 무기의 부모클래스입니다.
- 무기가 공통적으로 가지는 데이터와 메서드를 정의합니다.
- 각 무기 클래스(Punch, Sword …)는 Weapon 클래스를 상속받습니다.
- 실제 공격판정은 각 무기 클래스에서 구현합니다.
게임이 시작되면 다음 순서로 플레이어의 무기 세팅이 이루어집니다.
-
EquipmentUI 에서 플레이어 장비데이터 로드
- 로드된 데이터를가지고 WeaponManager의 SetWeapon() 호출
- 만약 무기를 장착중이지 않은 상태라면 기본값(Punch) 전달
- SetWeapon() 함수에서 플레이어의 무기를 세팅
- 공격 애니메이션 설정
- 무기 프리팹 생성
- 현재 무기정보 갱신
- PlayerController에서 공격 입력처리
- 애니메이션 이벤트로 이펙트, 공격판정, 콤보공격 등을 처리
플레이어의 스킬 시스템은 다음과 같이 설계하였습니다.
-
SkillManager가 스킬데이터를 로드하여 딕셔너리에 캐싱
-
플레이어가 스킬키 입력으로 SkillManager에게 스킬사용요청
- 딕셔너리에서 스킬데이터를 찾아 스킬인스턴스를 생성
- 스킬인스턴스가 이미 있다면 풀에있는 인스턴스를 재사용
- 스킬인스턴스가 없다면 새로 만들어 사용
- 스킬 사용 후 풀에 넣어놓기
스킬은 게임을 플레이하면서 가장 많이 사용되는것중에 하나입니다.
따라서 매번 스킬 인스턴스를 생성하지않고, 풀링을 통해 스킬인스턴스를 재활용할 수 있도록 설계하였습니다.
플레이어는 3가지 스킬을 사용할 수 있습니다.
- Slash : ‘검’ 전용 스킬로, 검기를 날려 전방의 적들을 공격합니다.
- IceShot : ‘스태프’ 전용 스킬로, 마법진을 생성하여 그 위의 적들을 지속적으로 공격합니다.
- Buff : ‘공용’ 스킬로, 사용시 플레이어의 공격력과 방어력을 일정시간 증가시킵니다.
몬스터
몬스터 AI는 상태(FSM)패턴을 적용하여 설계하였습니다.
몬스터는 다음과 같은 상태를 가집니다.
- IDLE : 대기상태. 플레이어가 다가가기 전까지 가만히 있습니다.
- CHASE : 쫓기상태. 공격하기위해 플레이어를 쫓아갑니다.
- ATTACK : 공격상태. 플레이어가 공격사거리안에 들어와 공격합니다.
- DIE : 죽음상태. 체력이 0이되어 죽습니다.
몬스터는 다음과 같은 동작을 수행합니다.
-
몬스터가 소환될 때 “Idle” 상태를 가지도록 초기화합니다.
- 특정조건(플레이어 탐지, 사거리내 접근 등)에 의해 몬스터 현재상태를 변경S합니다.
- 몬스터 상태를 변화시키는 작업은 “StateMachine”에서 수행합니다.
- 어떤 상태에 진입하고나면 상태에따른 동작을 수행합니다.
따라서,
몬스터의 상태가 변하는 조건의 정의는 몬스터가,
상태를 변경하는 작업은 StateMachine가,
변경된 상태에서의 동작은 상태 클래스가 수행하게됩니다.
게임내 여러 매니저클래스들
게임내에서 하나의 인스턴스만 존재해야하는 주요 매니저 클래스들은 다음과 같습니다.
- DataManager
- 게임 데이터를 Load & Caching. 플레이어의 데이터를 주기적으로 Save
- AudioManager
- BGM, SFX 데이터를 로드하고 출력
- DamageTextManager
- 게임에서 발생하는 데미지를 출력
- UIManager
- UI 활성/비활성화
- ResourceManager
- 런타임 에셋로드
매니저 클래스는 Singleton 디자인 패턴으로 작성되었으며, Singleton 클래스를 상속받아 사용합니다.
DataManager
DataManager 클래스의 주요 기능은 다음과 같습니다.
- 아이템, 플레이어 JSON 데이터를 Load & Caching
- 플레이어 데이터를 주기적으로 Save
- 아이템 데이터 검색 및 반환
- 플레이어 데이터 접근 제공
아이템 JSON 데이터는 다음과 같이 작성되어 있습니다.
// 예시 방어구 데이터 ArmorData.json
{
"Top": [
{
"id": 20001,
"itemName": "낡은 갑옷",
"itemToolTip": "낡은 갑옷이다.\n방어력+5",
"itemExplanation": "방어력+5",
"itemIcon": "Item_ArmorItem_Top_01.png",
"itemPrice": 500,
"defense": 5,
"type": "Armor",
"subType": "Top"
},
{
"id": 20002,
"itemName": "단단한 갑옷",
"itemToolTip": "단단한 갑옷이다.\n방어력+10",
"itemExplanation": "방어력+10",
"itemIcon": "Item_ArmorItem_Top_02.png",
"itemPrice": 1100,
"defense": 10,
"type": "Armor",
"subType": "Top"
}
],
"Shoes": [
{
"id": 21001,
"itemName": "낡은 장화",
"itemToolTip": "낡은 신발이다.\n방어력+3",
"itemExplanation": "방어력+3",
"itemIcon": "Item_ArmorItem_Shoes_01.png",
"itemPrice": 300,
"defense": 3,
"type": "Armor",
"subType": "Shoes"
},
{
"id": 21002,
"itemName": "판금 장화",
"itemToolTip": "단단한 신발이다.\n방어력+6",
"itemExplanation": "방어력+6",
"itemIcon": "Item_ArmorItem_Shoes_02.png",
"itemPrice": 700,
"defense": 6,
"type": "Armor",
"subType": "Shoes"
}
],
"Gloves": [
{
"id": 22001,
"itemName": "허름한 장갑",
"itemToolTip": "허름한 장갑이다.\n방어력+3",
"itemExplanation": "방어력+3",
"itemIcon": "Item_ArmorItem_Gloves_01.png",
"itemPrice": 400,
"defense": 3,
"type": "Armor",
"subType": "Gloves"
},
{
"id": 22002,
"itemName": "부드러운 장갑",
"itemToolTip": "부드러운 장갑이다.\n방어력+6",
"itemExplanation": "방어력+6",
"itemIcon": "Item_ArmorItem_Gloves_02.png",
"itemPrice": 900,
"defense": 6,
"type": "Armor",
"subType": "Gloves"
}
]
}
각 아이템 데이터는 ID 의 범위를 나눠 데이터 카테고리를 분류하려고했습니다.
예를들어 포션류 아이템은 10001 ~ 19999, 방어구류 아이템은 20001 ~ 29999
아이템을 생성하는 등의 요청이 발생하면 캐싱해둔 데이터를 딕셔너리에서 찾아 사용하여 불필요한 반복적 데이터로딩이 필요없도록 하였습니다.
// 아이템 데이터 접근 예시
// 아이템 타입별 반환
ItemData ItemTypeById(int id)
{
if (id > 10000 && id < 20000)
{
PortionItemData temp = DataManager.Instance.GetPortionDataById(id);
return temp;
}
else if (id > 20000 && id < 30000)
{
ArmorItemData temp = DataManager.Instance.GetArmorDataById(id);
return temp;
}
else if (id > 30000 && id < 40000)
{
WeaponItemData temp = DataManager.Instance.GetWeaponDataById(id);
return temp;
}
else
return null;
}
AudioManager
AudioManager의 주요 기능은 다음과 같습니다.
- BGM, SFX 데이터 Load & Caching
- 풀링을 통한 성능 최적화
- 게임내 UI로 볼륨제어
효과음은 게임을 플레이하며 굉장히 자주 출력됩니다.
그때마다 효과음 출력을 위해 새로운 AudioSource를 생성하기보다, 미리 생성해두고 재사용하는 풀링을 활용해 구현하였습니다.
또한 여러 효과음이 동시에 재생될 수 있도록하였고, 반복 재생되는 효과음의 경우 추적하여 원할때 중지할 수 있도록 하였습니다.
// 오디오 매니저 활용 예시
// 타이핑 효과
private IEnumerator TypePage(string page)
{
isTypipng = true;
dialogueText.text = "";
AudioManager.Instance.PlaySFX("DialogueEffect");
foreach (char letter in page.ToCharArray())
{
dialogueText.text += letter;
yield return new WaitForSeconds(typingSpeed);
}
isTypipng = false;
AudioManager.Instance.StopSFX("DialogueEffect");
}
- 효과음 플레이를 위해 PlaySFX() 메서드를 호출합니다.
- 이때 플레이하고자하는 SFX의 ID를 인자로 넘깁니다.
- 플레이되는 효과음 데이터의 loop 여부에 따라 반복 실행될 수 있습니다.
- 이 경우, 반복재생되는 효과음의 중지를 위해 StopSFX() 메서드를 호출하여 중지합니다.
DamageTextManager
DamageTextManager 주요 기능은 다음과 같습니다.
- 플레이어의 공격 히트시 데미지 텍스트 출력
- 떠오르는 텍스트 시각효과
- 풀링을 통한 성능 최적화
데미지표시 또한 게임 플레이에서 가장 많이 출력되는것중 하나입니다.
따라서 풀링을 활용하였고, 데미지 발생시 지정된 위치에 가한 데미지를 표시하도록 하였습니다.
데미지가 떠오르는 시각효과를 추가하여, 밋밋함을 덜어내려했습니다.
UIManager
UIManager 주요 기능은 다음과 같습니다.
- UI의 활성화 및 비활성화
- 스택을 활용하여 가장 최근에 활성화된 UI부터 차례로 비활성화
키보드 입력을 통해 여러 UI(인벤토리, 캐릭터정보창, 메뉴 등)를 활성화 시키고
Escape키 입력을 통해 활성화 되어있는 UI를 비활성화 시키는 작업을 수행합니다.
스택 자료구조를 사용하여, UI를 비활성화 시킬때는 가장 최근에 활성화된 UI부터 차례로 비활성화 시킵니다.
활성화 되어있는 UI가 없을 때 Escape 키 입력을 통해 메뉴 UI를 활성화 시킬 수 있습니다.
ResourceManager
ResourceManager 주요 기능은 다음과 같습니다.
- Addressable 에셋을 활용한 런타임 에셋 로드 및 캐싱
- 비동기 로드 및 메모리 최적화
게임 플레이동안에 에셋을 로드할 방법을 찾다가 Addressable 시스템을 사용하게 되었습니다.
여러 이미지아이콘, Prefab, 사운드등을 Addressable Group에 등록해놓고
런타임중 필요할 때 Load하여 사용할 수 있습니다.
// 사용 예시
// 아이템 아이콘 등록
public void SetItemIcon(string itemSprite)
{
if (itemSprite != null)
{
// 아이콘 데이터 가져오기
ResourceManager.Instance.LoadIcon(itemSprite, sprite =>
{
// 성공
if (sprite != null)
{
// 아이콘 이름 저장
iconName = itemSprite;
// 아이콘 설정
iconImage.sprite = sprite;
ShowIcon();
}
else
{
Debug.Log($"Failed to load icon for item : {itemSprite}");
}
});
}
else
{
RemoveItemIcon();
}
}
로드가 완료되면 콜백함수를 통해 결과를 전달합니다.
다만, 비동기식으로 동작하기 때문에 작업 처리의 순서에 유의하여야합니다.
이밖에도 InventoryManager, GameManager, DungeonManager 등의 매니저 클래스들이 존재합니다.
프로젝트를 마치며
작년 10월, ‘RPG 게임을 한번 만들어보자’는 다짐으로 프로젝트를 시작했습니다.
첫 장기 프로젝트였던만큼 의욕은 넘쳤지만 작은 시스템 하나만드는것도 쉽지않았고, 설계를 실패해 처음부터 다시 시작하는 일도 부지기수였습니다.
캐릭터 움직임부터 충돌 처리, UI 구성, 데이터 저장등 모든 것을 직접 설계하고 구현해야 했기에 매 순간이 도전이었던것 같습니다.
하지만 덕분에 게임 개발의 과정을 처음부터 끝까지 온전히 경험할 수 있었고, 단순히 기능을 만드는것을 넘어 ‘어떻게 설계해야 할지’에 대한 방향을 잡는것을 약간이나마 터득할 수 있었습니다.
특히 시스템 구조를 스스로 설계하면서, 유지보수성과 확장성을 고려한 코드 작성이 얼마나 중요한가에 대해서 알게되었습니다. RPG 게임의 경우 그것이 더 중요했기때문에 이러한 객체지향적 사고를 기를 수 있는 좋은 경험이 되었습니다.
물론 혼자 개발하면서 벽에 부딪힌 순간도 많았고, 디버깅에 며칠씩 매달리기도 했으며, 하루일과후 개발에 손을 대는것조차 쉽지는 않았습니다.
결과적으로 이 프로젝트는 단순히 ‘게임을 만든것’ 이상으로 제게는 기술적인 성장뿐아니라, 문제를 해결해나가는 능력, 스스로를 억제하며 필요한일에 집중하는 인간으로서의 성장을 할 수있었습니다.
댓글남기기