씬-레이어-오브젝트-컴포넌트 계층 구조


개요

자작 게임 프레임워크 구조는 씬(Scene) → 레이어(Layer) → 오브젝트(Object) → 컴포넌트(Component) 순으로 구성됐습니다. 객체지향 설계 원칙을 바탕으로 각 단계의 역할을 명확히 구분하며, 효율적인 관리유연한 확장성을 함께 제공합니다.


계층 구조 설계도

이 설계도는 각 클래스의 계층 구조를 시각적으로 보여줍니다.


클래스 목록 및 설명

⚠️ 참고: 씬-레이어-오브젝트-컴포넌트 계층 구조 설명을 위해 간소화한 코드입니다.

1. CScene 클래스

class CScene abstract
{
	friend class CSceneManager;
	
protected:
	CScene();
	virtual ~CScene();
	
protected:
    std::vector<CLayer*> mLayers;
	
protected:
	virtual bool Enter(void* payload = nullptr) = 0;
	virtual bool Exit()  = 0;
	
    virtual void Update(float deltaTime);
    virtual void LateUpdate(float deltaTime);
    virtual void Render(SDL_Renderer* renderer);
	
public:
    template <typename T, int initialCapacity = 50>
    T* InstantiateObject(const std::string& name, ELayer::Type type);
};


2. CLayer 클래스

class CLayer
{
	friend class CScene;
	
public:
	CLayer();
	~CLayer();
	
private:
    std::vector<class CObject*> mObjects;
	ESort::Type mSort = ESort::Y;
	
protected:
	void Update(float deltaTime);
	void LateUpdate(float deltaTime);
	void Render(SDL_Renderer* renderer);
	
public:
	void AddObject(CObject* obj) { mObjects.emplace_back(obj); }
	
private:
	static bool SortY(CObject* objA, CObject* objB);
};

  • 역할:
    • 레이어에 속한 모든 오브젝트를 관리하는 클래스입니다.
      • 오브젝트를 순차적으로 업데이트, 지연 업데이트, 렌더하며 필요 시 Y축 정렬을 수행합니다.
  • 핵심 함수들:
    • ~CLayer():
      • 레이어 소멸자. 소속된 모든 오브젝트를 메모리 풀을 통해 해제합니다.
    • void Update(float deltaTime):
      • 오브젝트를 순차적으로 업데이트합니다.
        • !Active 상태인 오브젝트는 제거 대상으로 표시합니다.
        • !Enable 상태인 오브젝트는 업데이트를 건너뜁니다.
    • void LateUpdate(float deltaTime):
      • 오브젝트를 역순으로 지연 업데이트합니다.
        • !Active 상태인 오브젝트는 제거 후, 메모리 풀에 반환합니다.
        • !Enable 상태인 오브젝트는 지연 업데이트를 건너뜁니다.
    • void Render(SDL_Renderer* renderer):
      • Y축 정렬이 설정된 경우, 모든 오브젝트를 Y좌표 값 기준으로 1회 정렬합니다.
      • 오브젝트를 순차적으로 렌더합니다.
        • !Active 또는 !Enable 상태인 오브젝트는 렌더를 건너뜁니다.

3. CObject 클래스

class CObject abstract : public CEntityBase
{
	friend class CScene;
	friend class CLayer;
	
protected:
	CObject();
	virtual ~CObject();
	
protected:
	CScene* mScene;
	CLayer* mLayer;
	
	CComponent* mRootComponent;
	
protected:
	virtual bool Init();
	virtual void Update(float deltaTime);
	virtual void LateUpdate(float deltaTime);
	virtual void Render(SDL_Renderer* renderer);
	
	virtual void Release() = 0;
	
public:
	CTransform* GetTransform() const { return mRootComponent->GetTransform(); }
	CComponent* GetComponent(const std::string& name = "")
	{
		if (name.empty())
			return mRootComponent;
			
		size_t hashID = std::hash<std::string>()(name);
		return mRootComponent->FindComponent(hashID);
	}
	template <typename T>
	T* GetComponent() const { return mRootComponent->FindComponent<T>(); }
	
	template <typename T, int initialCapacity = 10>
	T* AllocateComponent(const std::string& name);
};

  • 역할:
    • 씬과 레이어에 속하는 모든 오브젝트 클래스가 상속받는 추상 클래스입니다.
    • 오브젝트는 최상위 컴포넌트 mRootComponent를 중심으로 컴포넌트 계층을 구성합니다.
      • mRootComponent를 업데이트, 지연 업데이트, 렌더합니다.
  • 핵심 변수:
    • CComponent* mRootComponent:
      • 오브젝트의 최상위 컴포넌트입니다.
      • 오브젝트의 컴포넌트 계층 시작점이며, CTransform을 포함입니다.
  • 핵심 함수들:

4. CComponent 클래스

class CComponent : public CEntityBase
{
	friend class CObject;
	
protected:
	CComponent();
	virtual ~CComponent();
	
protected:
	size_t mTypeID = -1;
	
	CObject*    mObject    = nullptr;
	CTransform* mTransform = nullptr;
	
	CComponent* mParent = nullptr;
	std::vector<CComponent*> mChilds;
	
protected:
	virtual bool Init();
	virtual void Update(float deltaTime);
	virtual void LateUpdate(float deltaTime);
	virtual void Render(SDL_Renderer* renderer);
	
	virtual void Release();
	
public:
	CObject* GetObject() const { return mObject; }
	CTransform* GetTransform() const { return mTransform; }
	
	void AddChild(CComponent* child);
	bool DeleteChild(CComponent* child);
	
private:
	CComponent* FindRootComponent();
	CComponent* FindComponent(size_t id);
	
	template <typename T>
	T* FindComponent();
};

  • 역할:
    • 오브젝트의 실질적 기능을 수행하는 모든 컴포넌트가 상속받는 클래스입니다.
    • 컴포넌트 계층 구조를 관리하며, 다른 컴포넌트를 자식으로 포함할 수 있습니다.
  • 핵심 함수들:
    • CComponent():
      • 컴포넌트 생성자. 트랜스폼을 메모리 풀에서 생성 및 초기화합니다.
    • virtual ~CComponent():
      • 컴포넌트 소멸자. 모든 자식 컴포넌트와 트랜스폼을 메모리 풀에 반환합니다.
    • virtual bool Init():
      • 모든 자식 컴포넌트의 초기화 함수를 호출하며, 중간에 실패하면 false를 반환합니다.
    • virtual void Update(float deltaTime):
      • 컴포넌트를 순차적으로 업데이트합니다.
        • !Active 상태인 컴포넌트는 제거 대상으로 표시합니다.
        • !Enable 상태인 컴포넌트는 업데이트를 건너뜁니다.
    • virtual void LateUpdate(float deltaTime):
      • 컴포넌트를 역순으로 지연 업데이트합니다.
        • !Active 상태인 컴포넌트는 제거 후, 메모리 풀에 반환합니다.
          • 이 과정에서 트랜스폼 계층 관계도 함께 정리됩니다.
        • !Enable 상태인 컴포넌트는 지연 업데이트를 건너뜁니다.
    • virtual void Render(SDL_Renderer* renderer):
      • 컴포넌트를 순차적으로 렌더합니다.
        • !Active 또는 !Enable 상태인 컴포넌트는 렌더를 건너뜁니다.
  • 특징:
    • 해당 컴포넌트 클래스는 계층 구조를 유연하게 구성할 수 있으며, 이미지는 그 예시를 보여줍니다.

맺는 말

씬-레이어-오브젝트-컴포넌트 계층 구조를 설계하면서 객체지향 설계 원칙실무적으로 적용하는 경험을 쌓을 수 있었습니다. 이를 통해 복잡한 게임 요소를 체계적으로 구성하고 관리하며, 유지보수와 확장이 한층 더 용이함을 확인했습니다.