Nirvana

멀티 액션 로그라이크 게임

Role
클라이언트 프로그래머
Engine
Unreal Engine 5.3
Platform
PC
Team Size
22명
Duration
2023.01 ~ 2023.11 (8개월)

프로젝트 개요

역할 및 기여

'로그라이크' 장르의 특성을 티베트 불교의 '윤회'라는 교리에 비유하여 제작한 게임입니다. 로그라이크 시초인 '로그'와 티벳 불교의 교리인 '윤회(육도윤회도)'를 결합한 컨셉으로 개발되었습니다.


총 22명의 팀원이 8개월 동안 협업하였고, Unreal Engine 5를 사용하여 제작했습니다. 저는 이 프로젝트에서 클라이언트 프로그래머를 맡았습니다.

또한, 파트장을 맡게 되어 관련된 기여도 같이 진행했습니다.


개발 종료 후 청강 CGC 행사(네오위즈 판교 타워)에서 전시와 함께 마무리되었습니다.

Stove Store 에서 다운로드 가능

역할 및 기여

역할 및 기여

클라이언트 프로그래머

  • 게임 속 플레이어블 캐릭터 '파드마' 구현
  • 보스전 빙결 시스템 구현
  • 프로그래머들의 협업을 위한 주요 코드 구조 결정

프로그래머 파트장

  • 개발 환경 구축
  • 타 파트들과 소통하며 일정 조율, 업무 분배
  • 노션 페이지를 통해 협업 관련 주요 페이지 직접 작성

개발 환경 구축

1. 저장소 결정

본격적인 프로젝트를 시작하기 전, 개발 환경을 구축했습니다. LFS 용량을 고려하여 저장소를 선택했습니다.

저장소 Github GitLab Azure Devops
제한 용량 1GB 10GB 무제한

현 프로젝트에서는 Azure Devops 저장소를 사용했습니다.

맵 파일 관리 최적화

언리얼 엔진의 레벨 에셋(.umap)은 Google Drive로 관리했습니다. .umap 파일들은 크기가 커서 Git의 Pull, Push 작업을 느리게 만들었고, 저장소 최대 용량도 빨리 소모되게 하는 주 원인이었습니다. 이 문제를 해결하기 위해 맵 파일은 구글 드라이브로 공유하는 것으로 결정했습니다.

2. 버전 관리

역할 및 기여

프로젝트 버전관리의 측면에서 신경 쓴 것은 아래와 같습니다:

  • Main branch 작업: 팀 전원이 main branch에서 작업했습니다. Git에 미숙한 팀원들이 branch 를 사용하며 merge로 인한 이슈 해결에 개발 시간을 소모하지 않기 위해 결정했습니다.
  • Commit 메시지 규칙: 팀원들의 활동을 파악할 수 있고, 문제 원인도 빠르게 파악할 수 있다고 판단하여 규칙을 정했습니다.
  • Git 가이드 작성: Git에 익숙하지 않은 타 파트를 위해, 팀원들이 사용하는 Git 관리 툴에 맞춰 작성했습니다.

3. 협업 규칙

역할 및 기여
  • 폴더 구조 규칙:
    Unreal Engine에서 각 파트 별 폴더 구조 규칙을 정했습니다. 버전 관리에서 서로 충돌이 일어나지 않게 하기 위해 폴더를 구분하고 [이름] 폴더를 만들어 진행했습니다.


  • 개발 가이드 공유:
    Unreal Engine 개발 가이드를 작성하여 공유했습니다. 플러그인 적용 방법, 5.3 버전 업데이트 방법 등, 팀원들이 어려움 없이 프로젝트를 진행할 수 있도록 노션 페이지로 정리하여 공유했습니다.

주요 기능 및 구현 내용

개발 과정 로드맵

주요 기능을 구현한 내용들을 정리한 로드맵입니다. 시행착오를 겪으며 점진적으로 개선했습니다.

역할 및 기여

1. Component 구조로 시작

역할 및 기여

초기에는 각 스킬을 컴포넌트로 분리해 캐릭터에게 붙이는 구조로 시작했습니다.

문제점:

• 스킬의 개수가 많아질수록 캐릭터 클래스가 복잡해짐

• 관리해야 하는 데이터와 기능이 많아짐

• 타 파트들과 같은 캐릭터 블루프린트를 수정하기 어려웠음

• 협업 시 Git 충돌 문제가 잦게 발생함

위의 문제를 해결하기 위해, 구조를 다시 변경하게 되었습니다.

2. Action System 구조로 개선

Unreal Engine의 Game Ability System을 참고하여 Action System 기반의 구조로 캐릭터 시스템을 변경했습니다.

Action System 구성:

  • ActionComponent: Action들을 관리하고 실행하는 역할
  • Action: 실제로 기능을 수행하고, GamePlayTags로 관리됨
역할 및 기여

2-1. Action 의 역할

역할 및 기여

Action들은 캐릭터가 수행하는 하나의 스킬을 담당하며, 초기화 → 실행 → 중지 순으로 진행됩니다.

  • Action 초기화: 게임 시작 시 모든 Action들은 ActionComponent의 DefaultActions 배열에 추가되며, 초기화 작업을 진행합니다.
  • Action 실행: ActionComponent는 StartActionByName을 통해 DefaultActions에서 이름으로 특정 액션을 찾아 실행합니다.
  • Action 중지: 캐릭터의 애니메이션이 종료되거나, 다음 Action을 실행할 때 자동으로 기존 Action을 중지하도록 구현했습니다.

2-2. GamePlayTags를 통한 제어

역할 및 기여

Action이 시작될 때, Action은 자신이 실행 가능한지를 판단합니다. 판단하기 위하여 ActionComponent가 가진 ActiveGamePlayTags Container에 Blocked Tag의 여부를 체크합니다.

Blocked Tag가 없을 경우:

1. Action의 StartAction 함수를 호출

2. ActiveGamePlayTags Container에 GrantsTag를 추가

3. Action 기능 수행

Blocked Tag가 있을 경우: Action이 실행되지 않음

Action System 구조로 얻은 성과

• Action 클래스의 함수만 구현하면 스킬들을 만들 수 있음 (Initialize, StartAction, StopAction)

• ActionComponent로 Action들을 쉽게 관리할 수 있음

• 캐릭터의 동작 단위가 Action으로 구분되어 직관적이며, 디버깅이 편리함

2-1. 협업을 위한 Action Blueprint

역할 및 기여

C++의 Action 클래스들을 언리얼 에디터에서 각각의 Blueprint로 생성해서 관리했습니다.

직접 코드를 수정하지 않고도, 프로퍼티들을 에디터에서 쉽게 수정할 수 있게 되었습니다

협업의 측면에서:

Blueprint 안의 프로퍼티 값 변경 및 사용 방법을 공유해 기획자들과의 협업도 원활하게 진행했습니다.

3. AttackAction 구조로 확장

역할 및 기여

근접 전투 캐릭터인 "파드마"의 Action들은 공통적인 데이터와 동작이 많았습니다.

  • Resource 데이터:
    공격의 애니메이션 몽타주, 히트 이펙트
  • HitCheck 기능:
    무기를 휘두를 때 특정 애니메이션 프레임에만 실제 공격 판정 적용. 공통적으로 Damage, Radius, Range, Hit Frame과 같은 데이터들이 필요
  • AttackCancel 기능:
    공격 후 딜레이를 줄이기 위해서 공격을 캔슬하고 다른 공격을 수행하거나, 캐릭터가 이동할 수 있게 만듦

따라서 Action 클래스를 상속받아 확장했습니다.
위와 같은 필요한 속성들을 가지고,
기능을 수행하는 AttackAction을 구현했습니다.

4. Google Sheets로 데이터 관리

역할 및 기여

하지만 AttackAction이 기능을 수행하기 위한 데이터들이 많았고,

Action 클래스 블루프린트의 개수가 많아서 하나하나 클릭해 수정하는 것이 번거로웠습니다.

이를 해결하기 위해 Google Sheets를 사용했습니다.

역할 및 기여

AttackAction에서 필요한 데이터들을 모두 시트로 분리 후 틀을 만들어 기획자들에게 공유했습니다. (AttackProperties 시트, HitFrame 시트, 차징 공격 시트 등)

Google Sheets 사용 후 성과

• 기획자가 쉽게 원하는 데이터 추가 및 수정 가능

• 시트 수정 후 플레이만 하면 되므로 테스트 속도 향상

• 기획자들이 엔진을 사용하면서 생기는 실수가 줄어듦

공통적인 데이터들 이외에 고유의 데이터가 많은 AttackAction 들은 따로 시트를 추가해서 데이터를 파싱했습니다.

역할 및 기여

5. Unreal Editor 확장

역할 및 기여

Google Sheets의 시트들은 download_csv.exe를 실행하면 .csv 파일로 다운받아 Contents 폴더에 저장됩니다. 매번 파일 탐색기를 열어 더블 클릭해 실행시켜야 하는 것이 불편했습니다.

따라서 에디터를 확장해 버튼을 누르면 실행 파일이 실행되도록 구현했습니다. Editor Module을 구현해 툴바 버튼을 만들었고, 버튼을 눌렀을 때 download_csv.exe를 실행합니다.

에디터 확장 후 성과

• 엔진 내에서 편하게 csv 파일을 다운로드 가능

• 기획자, 프로그래머 모두 불편함을 해소

• 생산성이 더 올라가는 효과

5-1. Editor 확장 세부 구현 요소

Editor 를 확장하는 데 필요한 요소

1. Editor Module

2. Commands

3. Editor Style

역할 및 기여

Editor 확장 플로우

1. Editor Module Startup 시, Commands 와 StyleSet 을 등록.

2. 툴 바를 생성.

3. 생성 시 Command 와 Style 을 버튼에 맵핑

역할 및 기여

6. AttackActionData 로 분리

역할 및 기여

AttackAction 은 로직 뿐만 아니라 Google Sheets 에서 관리되는 모든 데이터들을 파싱 하며, 저장하고 있었습니다.

시간이 지날 수록 AttackAction 이 가진 데이터과 수행하는 기능이 많아졌습니다.

단일 책임 원칙에서 어긋날 뿐만 아니라 코드도 복잡해 진다고 판단했습니다.

따라서 AttackAction 의 데이터들과 파싱 기능을 분리해 AttackActionData 클래스로 구현했습니다.

7. AttackActionData 의 기능

역할 및 기여

AttackActionData 의 구조

1. Resource 와 Attack Properties, Frame 데이터
2. csv 파일을 파싱해 데이터들을 초기화하는 기능


AttackActionData 를 상속받아
공통 데이터들과 고유의 데이터들도 관리할 수 있습니다

또한 ParseOwnData 기능을 통해 고유의 데이터는 따로 파싱하도록 설계했습니다.

8. AttackActionData 와 DataAsset

역할 및 기여

이제 게임 시작 시 AttackAction 을 초기화할 때,
AttackActionData 를 같이 초기화합니다.


AttackActionData 는 UDataAsset 클래스를 상속받아

언리얼 기능 중 하나인 DataAsset 형식으로 에디터로 에셋을 열 수 있도록 구현했습니다.


그 이유는 디버깅 편의성입니다
에디터에서 직접 에셋을 클릭해, 파싱했을 때 데이터가
정상적으로 들어왔는지 확인할 수 있습니다.

또한, Read-Only 데이터로 설정해 실수를 방지하게 했습니다.