현재 활성 Scene 1개 관리하는 매니저
LoadScene() 호출
-> 내부적으로 LoadTestScene()을 호출해 카메라 + 몬스터가 있는 테스트 씬을 생성
-> 그 씬을 activeScene에 넣고, Init() 호출해서 Awake() -> Start() 순서 실행
즉, Game에서 SCENE->Update()만 호출하지만, SceneManager가 알아서 씬 내부의 모든 GameObejct와 Component를 돌게 해주는 구조
SceneManager.h
#pragma once
class Scene;
class SceneManager
{
public:
SceneManager(shared_ptr<Graphics> graphics);
void Init();
void Update();
void LoadScene(wstring sceneName);
public:
shared_ptr<Scene> GetActiveScene() { return _activeScene; }
private:
shared_ptr<Scene> LoadTestScene();
private:
shared_ptr<Graphics> _graphics;
private:
shared_ptr<Scene> _activeScene;
};
SceneManager.cpp
#include "pch.h"
#include "SceneManager.h"
#include "Scene.h"
#include "GameObject.h"
#include "Transform.h"
#include "Camera.h"
#include "MeshRenderer.h"
#include "Game.h"
#include "ResourceManager.h"
#include "Mesh.h"
#include "Animator.h"
SceneManager::SceneManager(shared_ptr<Graphics> graphics)
: _graphics(graphics)
{
}
void SceneManager::Init()
{
if (_activeScene == nullptr)
return;
_activeScene->Awake();
_activeScene->Start();
}
void SceneManager::Update()
{
if (_activeScene == nullptr)
return;
_activeScene->Update();
_activeScene->LateUpdate();
_activeScene->FixedUpdate();
}
void SceneManager::LoadScene(wstring sceneName)
{
_activeScene = LoadTestScene();
Init();
}
shared_ptr<Scene> SceneManager::LoadTestScene()
{
shared_ptr<Scene> scene = make_shared<Scene>();
// Camera GameOjbect 생성
{
shared_ptr<GameObject> camera = make_shared<GameObject>(_graphics->GetDevice(), _graphics->GetDeviceContext());
{
camera->GetOrAddTransform();
camera->AddComponent(make_shared<Camera>());
scene->AddGameObject(camera);
}
}
// Monster GameObject 생성
{
shared_ptr<GameObject> monster = make_shared<GameObject>(_graphics->GetDevice(), _graphics->GetDeviceContext());
monster->GetOrAddTransform()->SetPosition(Vec3(1.f, 1.f, 0.f));
{
monster->GetOrAddTransform();
auto meshRenderer = make_shared<MeshRenderer>(_graphics->GetDevice(), _graphics->GetDeviceContext());
monster->AddComponent(meshRenderer);
//monster->GetTransform()->SetScale(Vec3(2.f, 2.f, 1.f));
//...
// Material 설정
auto material = RESOURCES->Get<Material>(L"Default");
meshRenderer->SetMaterial(material);
// mesh 설정
auto mesh = RESOURCES->Get<Mesh>(L"Rectangle");
meshRenderer->SetMesh(mesh);
}
// Animator 설정
{
auto animator = make_shared<Animator>();
monster->AddComponent(animator);
auto anim = RESOURCES->Get<Animation>(L"SnakeAnim");
animator->SetAnimation(anim);
}
scene->AddGameObject(monster);
}
return scene;
}
GameObject들을 들고 있는 컨테이너 (각 GameObject 내부에서 Transform, MeshRenderer, Animator, MonoBehaviour 등)
SceneManager에서 Awake/Start/Update/LateUpdate/FixedUpdate 호출하면 Scene은 "씬에 포함된 모든 GameObject를 순회:하며 같은 이름의 함수 호출
즉, 게임 전체에서 한 씬의 수명(Life Cycle)을 관리하는 단위
Scene.h
#pragma once
class GameObject;
class Scene
{
public:
void Awake();
void Start();
void Update();
void LateUpdate();
void FixedUpdate();
public:
void AddGameObject(shared_ptr<GameObject> gameObject);
void RemoveGameObject(shared_ptr<GameObject> gameObject);
const vector<shared_ptr<GameObject>>& GetGameObjects() { return _gameObjects; }
private:
vector<shared_ptr<GameObject>> _gameObjects;
};
Scene.cpp
#include "pch.h"
#include "Scene.h"
#include "GameObject.h"
void Scene::Awake()
{
for (const shared_ptr<GameObject>& gameObject : _gameObjects)
{
gameObject->Awake();
}
}
void Scene::Start()
{
for (const shared_ptr<GameObject>& gameObject : _gameObjects)
{
gameObject->Start();
}
}
void Scene::Update()
{
for (const shared_ptr<GameObject>& gameObject : _gameObjects)
{
gameObject->Update();
}
}
void Scene::LateUpdate()
{
for (const shared_ptr<GameObject>& gameObject : _gameObjects)
{
gameObject->LateUpdate();
}
}
void Scene::FixedUpdate()
{
for (const shared_ptr<GameObject>& gameObject : _gameObjects)
{
gameObject->FixedUpdate();
}
}
void Scene::AddGameObject(shared_ptr<GameObject> gameObject)
{
_gameObjects.push_back(gameObject);
}
void Scene::RemoveGameObject(shared_ptr<GameObject> gameObject)
{
auto findIt = std::find(_gameObjects.begin(), _gameObjects.end(), gameObject);
if (findIt != _gameObjects.end())
{
_gameObjects.erase(findIt);
}
}