개발일지

[ProjectRE] 개발 일지 1

타자치는 문돌이

프로젝트가 개발 단계의 한 사이클을 돌았다고 할 정도가 진행되었다.
이제 어떤 게임을 만드려고 하는지 보이는 프로토타입 정도가 되었다.
며칠 정도 현재까지 개발한 내용을 검토하며 다져놔야 할 부분을 다질 타이밍인 것 같다.


복기

개발 방식

LLM 도입

초창기에는 GPT를 참고용으로 활용하다가 Enhancement System 개발 즈음부터 본격적으로 Codex와 Gemini cli를 도입했다. 몇 달 사이에 너무 많이 발전했다. 몇 번의 시행착오와 조사 끝에 나만의 작업 흐름을 완성했다.

1. 기획 문서 작성
구현하려는 기능의 기획을 작성한다. 어떤 기능이고, 어떤 식으로 쓰일 지, 규칙 등을 작성하고 GPT로 구체화해서 완성했다. 어떻게 구현할지 코드 관련 내용은 모두 빼고 기획 측면에서 원하는 내용을 적었다.

2. 관련 자료 조사
AI로 게임을 개발하며 있던 가장 큰 문제는(특히 언리얼), 이미 구현되어 있는 기능을 새로 구현하려 한다는 점이었다. 예를 들어 Ability System에는 이미 사용 가능한 Target Data와 활용 함수들이 정의되어 있지만, 이걸 활용하는 대신 새로운 Target Data를 정의하고 사용하려 한다. 이를 막기 위해 이 단계를 추가했다.
Codex로 1의 기획을 구현하기 위해 알아두어야 할 프로젝트의 내용과 Unreal Engine의 내용, 보편적으로 구현하는 방식을 조사해 작성한다. AbilityBase를 구현하려 하면 현재 Player ASC, Gameplay Ability 등에 대해 조사해 작성한다.

3. 구현 기획 문서 작성
1과 2를 바탕으로 새 기능을 어떻게 구현할 지 작성한다. 클래스가 어떤 함수를 가지고, 어떤 로직으로 작동하며, 어떤 기능을 사용할지를 정리한다.

4. 코드
실제로 구현할 코드나 Blueprint를 작성한다.

각 단계에서 마음에 안들면 직접 수정하거나 전 단계로 돌아가 내가 원하는 대로 기획이 코드로 구체화되도록 방향을 잡았다. 그리고 작성한 문서는 Gemini cli가 검토하고 피드백을 한다.

결과물은 상당히 마음에 들고 원하는 방향으로 구현하지만 생각보다 검토에 시간이 오래 걸린다. 각 단계마다 300~500줄 정도의 문서가 생성되고 검토해야 한다. 쓸데없는 말을 줄이는 방향으로 promts를 설정할 수 있다면 찾아봐야겠다.


주요 구현

Experience System

 

Lyra와 모듈형 게임플레이

https://dev.epicgames.com/documentation/ko-kr/unreal-engine/game-features-and-modular-gameplay-in-unreal-engineGame Feature와 ExperienceLyra는 여러가지 모드가 존재하고, 이를 Experience라는 단위로 나누어 구분한다.이때, 필요없

code-in-coffee.tistory.com

Lyra의 Experience System을 구현해 초기화 로직을 관리한다. 아직 간단한 역할만 하며 현재 주요 역할은 Player의 Pawn, Abilityset, InputConfig 등을 연결하고 초기화 타이밍을 관리하며 Experience를 로드하는 GameMode 역할이다. Main Menu -> Room -> Gameplay 부분과 Async Load가 완성되면 더 강조될 것 같다.

 

GAS 기반 전투 시스템

Attributeset을 기반으로 하는 능력치 시스템과, Gamplay Ability를 바탕으로 하는 AbilityBase, Gameplay Tag를 활용한 Input System과 전투 제어 로직을 구현했다. Blueprint에서 쉽게 확장 가능한 구조로 만들어 다양한 스킬을 쉽게 구현할 수 있다.

 

Enhancement System 

로스트아크의 엘릭서 시스템을 가져온 강화 시스템을 구현했다. 강화 미리 보기의 구현이 특히 힘들었다.

 

Widget Controller 기반 UI

Widget Controller를 기반으로 UI를 관리하는 HUD 시스템을 만들었다. WC에서 쉽게 필요한 값을 전달 받아 Widget이 보여준다. Widget 크기와 위치 관련해서는 공부가 더 필요하다.

 

BT 기반 Enemy

언리얼 BT와 Blackboard를 활용한 Enemy 로직을 구현했다.


막힌 부분

기획과 에셋

사실 기획한 내용은 지금까지의 구현이 대부분이다. "전투->강화가 반복되는, 엘릭서 방식 강화를 사용하고 다양한 무기를 쓸 수 있는 쿼터뷰 액션 로그라이크". 여기서 더 나아가려면 기획을 확정해야 한다. 메인 컨셉을 어떻게 할지를 정해야 무기와 스킬, 적, 맵 스타일, 스토리 등이 정해진다. 이게 어려운 이유는 에셋이다. 메인 컨셉에 맞춰 에셋을 구하는 것보다 에셋에 맞춰 메인 컨셉이 강제로 정해질 확률이 높다. 3D 에셋을 거의 못 만지는 개발자의 한계다. 에셋을 찾으며 느낀 것은 생각보다 쿼터뷰에 맞는 애니메이션을 찾기 어렵다는 것(Paragon 에셋을 쓰니까 너무 붕쯔붕쯔 느낌이라 다른 애니메이션을 찾아야 했다)과 무료 VFX가 많이 없다는 것이다.
돈을 쓰거나 AI를 써야한다.

 

Map 구현 방식

현재는 BP_Stage를 소환하는 방식으로 맵을 구현 했다. 그러나 배경을 더 신경 쓴다면 스테이지 여러 개가 채워진 맵을 만드는 것이 나을 것 같다. 아니면 PCG도 고려해 볼 만하다.

 

Enhancement System

강화 시스템은 선택지에 따라 다양한 효과를 준다.
카드 게임을 어떻게 구현할지 고민하며 생각해 본 것인데, 나라면 하스스톤 카드의 효과를 어떻게 구현할까?
비슷한 기능으로 묶어서 대상-비용-규칙-효과 데이터를 저장하고 이걸 해석해서 발동하는 것이 정석적이고, Enhancement System도 이렇게 구현했지만, 사실 규칙이 복잡해지고 양이 많아지면 오히려 이걸 각각 구현하는 것이 더 낫지 않을까라는 생각도 한다. 특히 새 효과를 위해 규칙 전체나 효과 전체에 수정을 해야 하는데 이 수정이 다른 모든 카드에 영향이 없을지를 확신할 수 있을까? 하스스톤이라면 가능할 것 같다고 생각이 든다면 유희왕은 어떨까? 그 말도 안 되는 카드 효과를 컨텍스트 해석으로 풀어낼 수 있는 것일까?

 

Loading Screen

맵과 맵의 전환에서 동작하는 시스템이라 아직 버그가 많다. 맵 전환하면 아주 짧게 로딩 안된 상태의 맵이 보일 때가 있다.

 

IGameMoviePlayer | Unreal Engine 5.7 Documentation | Epic Developer Community

An interface to the movie player we will use for loading screens and gameplay movies

dev.epicgames.com

이걸 써보는 것도 계획 중이다.


다음 개발 동안 생각해 볼 것

개발 방식

개발 방식과 관련해 몇 가지 변화를 주려고 한다.

LLM Wiki 도입

앤드류 카파시가 제안한 패턴으로, llm과의 대화를 일회성으로 끝내는 대신 llm wiki에 기록해 지식을 축적하고, 대화를 할 때 필요한 정보를 wiki에서 검색하는 방식이다.

 

llm-wiki

llm-wiki. GitHub Gist: instantly share code, notes, and snippets.

gist.github.com

현재도 비슷한 방식을 쓰고는 있다. 기능을 구현한 다음, 방금 개발한 기능을 요약하라고 한 뒤, IMPLEMENTATION_STATE.md에 기록하고 있다. 개발에서 맥락이 필요하면 이 문서를 참고해 정보를 긁어오지만, 이 문서는 벌써 1000줄을 넘어가 검색할 때 비효율적인 문서가 되었다. IMPLEMENTATION_STATE.md를 대체하는 기능으로 프로젝트에 한정한 llm wiki를 구성할 계획이다.

 

은근히 거슬리는 폴더 구조

Codex는 .gitignore를 반영하고, 이걸 수정할 방법이 아직 없는 것 같다. Gemini는 .gitignore 무시하기 옵션이 있지만 Codex는 찾을 수 없다. llm 관련 파일이 많이 존재하는데 .gitignore에 등록하면 무시되고, 안 하면 계속 unstaged change에 보인다. 생각해 낸 꼼수는 프로젝트 폴더를 감싸는 것이다.

기존에는 프로젝트 root에 .gemini, .agent폴더를 두고 여기서 Codex나 Gemini를 사용했다.

// 기존 구조
ProjectRE/  
├─ Source/  
├─ Content/
├─ ...
├─ .gemini/
├─ .agents/
│  ├─ commands/  
│  ├─ ...
│  └─ docs/
├─ .gitignore
├─ ...
└─ ProjectName.uproject
...

새로 구상 중인 방법은 프로젝트 폴더 밖에 llm 관련 파일을 놓고 실행하는 방식이다. 이러면 거슬리는 llm 파일을 git의 범위에서 뺄 수 있다.

ProjectRE/
├─ ProjectRE/  
│  ├─ Source/  
│  ├─ Content/
│  ├─ .gitignore
│  ├─ ...
│  └─ ProjectName.uproject
├─ .gemini/
├─ .agents/
├─ feature/
└─ wiki/

 

객체 지향

객체 지향적인 코드를 짜기 위해 노력했지만 ai를 활용한 개발을 하며 새로운 관점으로 생각해 보기 시작했다.

게임의 객체들이 단독으로 존재하고, 다른 요소를 모르거나 없어도 작동해야 한다.

객체의 내부를 모르는 상태에서도 로직이 돌아가면 ai도 상대 객체를 파악하지 않아도 된다. 아직 ai는 다른 요소를 파악하고 그것까지 감안해 줄 정도로 똑똑하지는 않다. 상대 객체 파악은 많은 토큰을 쓰기도 한다. 차라리 단독으로도 잘 작동하고 상호작용 가능한 객체를 만드는 것이 낫다고 생각한다. Component도 더 적극적으로 활용해야겠다. 역할과 기능이 얽힐수록 ai가 멍청한 대답을 준다.


도입해 볼 만한 기술

PCG, Level Streaming

맵을 PCG로 생성하는 것도 후보에 있다. 아니면 방마다 Level Streaming으로 로드/언로드 할 수도 있다. 맵은 어떻게 구현할지 더 고민해봐야 한다.

 

Motion Matching

이동 애니메이션을 아직은 크게 신경 안 쓰고 있지만 자연스러운 애니메이션 전환이 가능하다면 도입해보려고 한다. 다만 대부분 예제가 3인칭 백뷰 기준이라 그대로 적용하면 회전이 이상하게 동작한다. 이 문제를 고쳐야 한다.

 

Async Load

 

Gameplay Camera

자세히 조사는 안 한 기능이다. GAS와 조합이 좋아서 컷신 연출 등이 간편하면 사용해 볼 계획이다.


흠...

한 일주일 정도 쉬면서 프로젝트의 클래스 다이어그램을 그려봐야겠다. 프로토타입 정도까지 되니까 어떤 요소로 내가 원하는 것을 표현하면 될지 큰 그림이 잡혔다.

 

"대화를 바탕으로 이 게임이 완성됐을 때의 모습을 그려줘."

그림은 참 잘 그린단 말이지...

 

반응형