씬 매니저와 리소스 최적화 설계
개요
CSceneManager는 게임 진행 중 씬을 선입후출(FILO) 방식의 스택 구조로 관리하는 싱글톤입니다. 씬 전환은 일관된 상태 전이와 리소스의 안전한 생성 및 해제를 보장하며, 스마트 포인터 기반 리소스 관리로 이전 씬과 공유하는 리소스를 재로드 없이 넘겨받아 효율적인 메모리 사용과 빠른 전환을 지원합니다.
씬 전환 종류
씬 전환은 ChangeRequest(ETransition, ESceneState) 함수로 요청하며, 호출 시 전환 정보가 mPending에 저장되며, 다음 프레임의 Update(float) 함수가 시작될 때 ChangeApply()를 통해 처리됩니다.
| 전환 종류 | 역할 | 세부 단계 |
|---|---|---|
| PushScene() | 스택 최상단에 새로운 씬 추가 | 1. 새로운 씬 생성 2. 새로운 씬 리소스 로드 3. 스택 최상단에 새로운 씬 추가 4. 새로운 씬 Enter() 호출 |
| PopScene() | 스택 최상단 씬 제거 | 1. 스택 최상단 씬 Exit() 호출2. 스택 최상단 씬 리소스 언로드 3. 스택 최상단 씬 제거 |
| SwapScene() | 스택 최상단 씬 제거 후, 새로운 씬 추가 | 1. 새로운 씬 생성 2. 새 씬 리소스는 로드하되, 최상단 씬 공통 리소스는 재로드 없이 전달 3. PopScene() 호출4. 스택 최상단에 새로운 씬 추가 5. 새로운 씬 Enter() 호출 |
| ClearScenes() | 모든 씬 제거 | 1. 스택에 씬이 없을 때까지PopScene() 호출 |
| ClearThenPushScene() | 모든 씬 제거 후, 새로운 씬 추가 | 1. 새로운 씬 리소스 로드하되, 모든 씬과의 공통 리소스는 재로드 없이 전달 2. ClearScenes() 호출3. 스택 최상단에 새로운 씬 추가 4. 새로운 씬 Enter() 호출 |
씬 전환 리소스 관리 (코드 분석)
⚠️ 참고: 본 코드는 씬 전환 리소스 관리 방식의 설명을 위해 간소화한 코드입니다.
class CTextureManager { private: std::unordered_map<std::string, std::weak_ptr<CTexture>> mTextures; public: std::shared_ptr<CTexture> LoadTexture(...); } //---------------------------------------------------------------// class CFontManager { private: std::unordered_map<std::string, std::weak_ptr<CFont>> mFonts; public: std::shared_ptr<CFont> LoadFont(...); } //---------------------------------------------------------------// class CSoundManager { private: std::unordered_map<std::string, std::weak_ptr<CSFX>> mSFXs; std::unordered_map<std::string, std::weak_ptr<CBGM>> mBGMs; public: std::shared_ptr<CSFX> LoadSFX(...); std::shared_ptr<CBGM> LoadBGM(...); }
- 각
리소스 매니저는 리소스를std::weak_ptr로만 보관합니다. 이는 약한 참조만 유지하여 리소스의 소유권을 가지지 않으며, 실제 메모리 해제는 해당 리소스를shared_ptr로 소유하는 씬에서 모든 참조가 끊어질 때 자동으로 이루어집니다.
class CScene abstract { friend class CSceneManager; protected: CScene(); virtual ~CScene(); protected: std::vector<std::shared_ptr<class CTexture>> mTextures; std::vector<std::shared_ptr<class CFont>> mFonts; std::vector<std::shared_ptr<class CSFX>> mSFXs; std::vector<std::shared_ptr<class CBGM>> mBGMs; protected: virtual void LoadResources() = 0; void UnloadResources() { mTextures.clear(); mFonts.clear(); mSFXs.clear(); mBGMs.clear(); } }
CScene추상 클래스는CTexture,CFont,CSFX,CBGM등 다양한 리소스를std::shared_ptr로 관리합니다. 덕분에 씬은 필요한 리소스의 소유권을 명확히 가지며,UnloadResources()호출 시 벡터를 비워 참조를 모두 해제합니다. 스마트 포인터 기반 참조 관리로 사용하지 않는 리소스를 안전하게 정리할 수 있습니다.
void CSceneManager::SwapScene() { CScene* newScene = GetSceneFromState(mPending.pendingState); newScene->LoadResources(); CScene* oldScene = mScenes.back(); if (oldScene->Exit()) { oldScene->UnloadResources(); SAFE_DELETE(oldScene); mScenes.pop_back(); } mScenes.push_back(newScene); mScenes.back()->Enter(mPending.payload); }
SwapScene()는 새로운 씬을 먼저 생성해 리소스를 로드한 뒤, 기존 씬을Exit()하고 리소스를 언로드한 후 스택에서 제거합니다. 이 전환 과정에서는 이전 씬과 현재 씬이 공유하는 리소스를 재로드하지 않고 그대로 재사용하므로, 전환 지연을 최소화하고 메모리 사용 효율이 높아집니다.
맺는 말
CSceneManager의 씬 스택 구조와 스마트 포인터 기반 리소스 관리는 단순한 씬 교체를 넘어, 전환 과정의 안정성과 메모리 관리의 신뢰성을 높입니다. 이를 통해 다양한 씬 전환 패턴을 상황에 맞게 적용할 수 있으며, 프레임워크 전반에서 유연한 구조 확장과 장기적인 유지보수성을 지원합니다.