이번
EntityHandle

마우스 피킹을 구현하기 위해 Entity마다 고유한 int값을 필요로 한다. 이 값을 제공하기 위해서
EntityHandle이라는 클래스를 만들었다.
EntityHandle 클래스는 런타임에 부여받는 식별값으로 고정된 값이 아니라 바뀔 수 있다.
2^22개의 엔티티가 고유한 인덱스를 가질 수 있고 2^10만큼의 generation이 존재할 수 있다.
둘을 조합해서 32bit 정수인 unsigned int를 id로 제공한다.

generation을 따로 두는 이유는 위와 같은 문제를 해결하기 위함이다.
이 클래스를 Scene에서 각 게임엔티티가 생성될 때 할당한다.

설명하자면 freeIndices가 있는 경우 그 Indices 자리에 GameEntity 객체를 생성하고 없는 경우
새로운 index를 만들고 거기에 GameEntity 객체를 생성한다.
그리고 index의 generation값을 가져와서 이 값들을 기반으로 EntityHandle값을 생성한다.


Entity의 파괴도 구현은 해뒀는데 실행해보니 문제가 많아서 아직 못쓰는 기능이다.
일단은 파괴되면 entity가 가지고있는 component들과 자식컴포넌트들, 자신의 핸들을 모두 초기화하고
자기가 가지고있던 index의 generation값을 다음 entity를 위해 1 증가시켜주고 freeIndices에 반환하는 구조로 만들었다.
UUID
엔진에서 사용되는 이미지, 모델, 머티리얼, 씬 등을 원래는 문자열을 통해 관리하고 있었지만 아무래도 문자열로 관리하는 게 신경쓸 것도 많고 별로 효율적이지 않다는 생각이 들어서 uuid를 써보기로 했다.
유니티처럼 메타파일 만들어서 좀 그럴듯하게 보이고 싶은 부분도 있음.
The Cherno의 Hazel 엔진에서는 unsigned long long의 무작위 값을 uuid로 사용했지만 나는 이왕 만드는거 128bit 값으로 제대로 된 uuid를 적용하고자 했고 stduuid라는 라이브러리를 찾게 되었다.
https://github.com/mariusbancila/stduuid
GitHub - mariusbancila/stduuid: A C++17 cross-platform implementation for UUIDs
A C++17 cross-platform implementation for UUIDs. Contribute to mariusbancila/stduuid development by creating an account on GitHub.
github.com
왜 이걸 쓰냐하면 사실상 Windows로만 개발하고 있지만 처음 엔진 개발할 때 크로스플랫폼 엔진을 표방하고 있었기 때문에 라이브러리를 고를 때 이런 부분을 신경써서 골랐다.
아무튼 그래서

이런식으로 AssetHandle을 만들어 주었고 해쉬함수를 구현해줌으로써 unordered_map에서 키값으로서 동작할 수 있도록 구현했다.
Asset 관리 구조
이게 엄청 시간을 잡아먹었는데 구조를 짜야 될지 고민을 매우매우 많이 했는데 생각만하다가 하루이틀 지나다 보니까 아무것도 안만든채로 시간이 빨리 가더라
원래는 ResourceManager라는 싱글톤 객체에서 전부 관리하고 있었는데
구체적인 파일경로가 있는 객체의 경우는 관리하는 주체를 구분해줘야 한다는 생각이 들었다.
그래서 AssetManager를 구상했다.
어떤게 Asset에 들어가야하나부터 시작했다.
파일로부터 로드해야하는 객체들
- Shader, Model, Texture2D
- TextureCube(이건 아직 어떻게 관리해야할지 모름)
- Sound, Script (추가예정인 객체들)
여기에 해당하지 않는 RenderPass,PSO,Sampler,ShaderGroup,Mesh등의 객체들은 그대로 ResourceManager가 관리하는 구조를 채택했다.
ResourceManager도 변화가 있었는데


각각 따로 shared_ptr 객체로 존재하던 registry들을 공통 상속 인터페이스로 묶고 std::type_index를 key로 사용해서 관리하도록 바꿨다.
이제 다시 AssetManager 구현으로 돌아가보자.

그래서 생각 끝에 구현한 구조는 정말 허접해보이지만 이렇다.
AssetManager::GetAsset() 이런 식으로 전역에서 간단하게 Asset을 가져오고 싶었다는 생각이 컸다.



에셋으로 분류하고자하는 클래스들은 Asset 클래스를 상속받게 했다.

일단 대략적인 구조를 설명하면 특정 directory를 재귀 또는 비재귀적으로 돌면서
Asset의 확장자에 해당하는 파일이 있는지를 찾는다.
나중에 엔진 프로젝트를 만들게 되면 프로젝트 파일에 저장되어있는 Asset폴더의 Path가 들어가게 될 것을 상정하고 만들었다.
해당 파일을 찾게되면 파일명에 .ddmeta라는 확장자를 붙여서 메타파일이 존재하는지 확인한다.
.ddmeta의 dd는 Daydream Engine의 약자를 붙여봤다.
그래서 파일을 찾게되면 메타파일로부터 데이터를 읽어서 레지스트리에 해당 파일의 정보를 등록한다.
만약 메타파일을 못찾으면 현재 파일의 정보를 가지고 메타파일을 생성해준다.
메타파일 생성은 json과 yaml-cpp중에서 고르면 되는데 나는 yaml-cpp를 골랐다.
The Cherno 영상보고 따라하던 시절에 한번 써본게 좀더 친근하다고 생각해서 그렇게 됐다.

그러면 이런식으로 메타파일이 생성되게 된다.
아무튼 그래서 레지스트리에 등록된 메타데이터 정보를 가지고 있다가
GetAsset이 호출되면

assetCache에서 이 에셋이 실제로 로드가 되어있는지를 찾고 만약 없으면 새로 로드해서 Asset을 만들고
assetCache에 등록한다.
아무래도 시작할때 모두 생성하는게 아니다 보니 만약 에셋을 로드하는 상황이 생기면 로드하는 동안 프로그램이 멈추는 문제가 있어서 나중에 해결할 필요가 있다.
멀티스레드 프로그래밍에 두려움이 좀 있음

이건 경로를 통해서 찾는 함수인데 코드에서 경로를 통해서 에셋을 가져와야 하는 부분이 좀 필요해서 넣었다.
그리고 이제 게임엔진의 프로젝트 구조를 구축하려고 했는데
이 기간동안 너무 재미가 없어서 다시 렌더링 개발쪽으로 넘어가기로 했다.
대충 큰 구현내용들은 다 설명한거 같아서 끝.
'개인 공부 및 프로젝트 > Daydream Engine' 카테고리의 다른 글
| 자체 게임엔진 Devlog - Vulkan 렌더 스레드 문제 해결 (0) | 2026.04.08 |
|---|---|
| 자체 게임엔진 Devlog - 14 (0) | 2026.04.08 |
| 자체 게임엔진 Devlog - 12 (0) | 2025.10.27 |
| 자체 게임엔진 Devlog - 11 (0) | 2025.10.01 |
| 자체 게임엔진 Devlog - 10 (0) | 2025.09.18 |