DirecX12 | Lecture 14. Component (인프런)
DirectX12 강의 14. Component를 정리한 글입니다.
DirecX12 | Lecture 14. Component (인프런)
강의 정보 🎓
- 강의명: C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈 - Part2: 게임 수학과 DirectX12
- 플랫폼: 인프런
- 현재 섹션: Lecture 14 – Component
- 주요 내용: Component 기반의 엔진 개발을 위한 밑작업을 수행하였다.
게임 오브젝트 구조를 컴포넌트 기반(Component-based) 으로 구성하여 유연한 설계를 구현합니다.
(유니티처럼 → 컴포넌트 기반 / 언리얼은 상속 기반 + 컴포넌트)
1. GameObject, Component 구조 설계
생성된 클래스:
Component
GameObject
MeshRenderer
Transform
MonoBehaviour
2. Component 클래스
- enum class ComponentType 정의,
MonoBehaviour
를 마지막으로 정의 해준다. 주요 멤버 함수:
1 2 3 4 5 6 7 8 9 10 11
public: virtual void Awake() {} virtual void Start() {} virtual void Update() {} virtual void LateUpdate() {} private: // GameObject만 이 함수를 접근하도록 friend class GameObject; void SetGameObject(std::shared_ptr<GameObject> gameObject) { mGameObject = gameObject; }
주요 멤버 변수:
1 2 3
protected: COMPONENT_TYPE mType; std::weak_ptr<GameObject> mGameObject;
3. GameObject 클래스
상속 (스마트 포인터 전달에 필요)
1
class GameObject : public std::enable_shared_from_this<GameObject>
주요 멤버 함수:
1 2 3 4 5 6 7 8
public: void Init(); void Awake(); void Start(); void Update(); void LateUpdate(); void AddComponent(std::shared_ptr<Component> component); // 컴포넌트를 추가
주요 멤버 변수:
1 2 3
private: std::array<std::shared_ptr<Component>, FIXED_COMPONENT_COUNT> mComponents; std::vector<std::shared_ptr<MonoBehaviour>> mScripts;
4. MonoBehaviour & Transform
Component
상속- 기본적인 생성자/소멸자 구현
5. MeshRenderer
Component
상속Mesh
와Material
클래스 관리주요 멤버 함수:
1 2 3 4 5 6 7
virtual void Update() override { Render(); } void Render() { // GetTransform()->Update(); mMaterial->Update(); mMesh->Render(); }
주요 멤버 변수:
1 2
std::shared_ptr<Mesh> mMesh; std::shared_ptr<Material> mMaterial;
6. Mesh 수정
Material
,Transform
멤버 변수 삭제 (Component에서 받도록 변경)Render()
시 Material/Transform 관련 호출를 제거한다.
7. Game.cpp 변경
- 전역
GameObject
를 추가한다. Mesh
초기화 →GameObject::Init()
내부로 이동init 함수 내부:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
//... 버텍스, 인덱스 설정 등 gameObject->Init(); // Transform 추가 std::shared_ptr<MeshRenderer> meshRenderer = std::make_shared<MeshRenderer>(); { std::shared_ptr<Mesh> mesh = std::make_shared<Mesh>(); mesh->Init(device, commandQueueLayer, vertices, indexes); meshRenderer->SetMesh(mesh); } { std::shared_ptr<Shader> shader = std::make_shared<Shader>(); std::shared_ptr<Texture> texture = std::make_shared<Texture>(); shader->Init(device, rootSignature, depthStencilBuffer->GetDSVFormat(), L"..\\Resources\\Shader\\default.hlsli"); texture->Init(device, commandQueueLayer, L"..\\Resources\\Texture\\avatar.png"); std::shared_ptr<Material> material = std::make_shared<Material>(); material->SetShader(shader); material->SetFloat(0, 0.3f); material->SetFloat(1, 0.4f); material->SetFloat(2, 0.3f); material->SetTexture(0, texture); meshRenderer->SetMaterial(material); } gameObject->AddComponent(meshRenderer); commandQueueLayer->WaitForGpuComplete(); };
Game Update() 내부
1 2 3 4 5 6 7 8 9
void Game::Update() { Engine::GetInstance().Update(); Engine::GetInstance().RenderBegin(); gameObject->Update(); Engine::GetInstance().RenderEnd(); }
현재 문제 & 해결
문제
- MeshRenderer에서 Render 시
device
등 인자들이 필요하다. - Component Update() 에서도 동일 인자 필요 → GameObject Update 수정 필요
- 구조상 불필요한 수정이 우려된다.
해결
GameObject에 Update() 와 Render() 를 분리하여 해결하였다.
→ Component는 필요 시 Render() 를 오버라이드해서 사용한다.
요약
항목 | 설명 |
---|---|
Component 기반 구조 | GameObject + Component |
GameObject 역할 | Component 추가/Update/Render 관리 |
MeshRenderer 역할 | Mesh + Material 묶어서 렌더링 |
Mesh 구조 변경 | Material/Transform 제거 |
Game 흐름 변경 | GameObject 중심으로 관리 |
Render 구조 | GameObject에서 Update/Render 분리 |
느낀점 📝
느낀점 💡 컴포넌트 기반의 구조를 구현해보고 싶었는데 마침 강의에서 비슷한 형태로 구현하게 되어서 매우 좋았다. 이를 기반으로 나만의 미니 엔진을 구현해보고싶다는 욕구가 든다.
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.