Chapter 8. Scene Manager
카테고리: Unity Lesson 2
태그: Unity Game Engine
인프런에 있는 Rookiss님의 [C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part3: 유니티 엔진 강의를 듣고 정리한 필기입니다. 😀
🌜 강의 들으러 가기 Click
Chapter 8. Scene Manager
🚀 구조도
여태까지는 📜PlayerController에 Manager
로부터 GameManager 스러운 일들을 실행시켰는데, 플레이어도 씬에 동적으로 생성되는 존재라면 📜PlayerController에 Manager
를 호출하는 것은 바람직하지 않을 것이다. 게임 실행 中 내내 살아있는 선봉대 역할을 할 존재를 만들고 그에게 Manager
를 호출하는 일을 맡겨야 한다. 이 선봉대 역할을 📜Scene 에서 할 것
- 씬들. 각각 씬들만의 함수
- 📜BaseScene
- 📜GameScene
- 📜LoginScene
- 📜BaseScene
- 여러 씬들 한꺼번에 관리 👉 📜SceneManager
빈 오브젝트 @Scene
만들어서 그 곳에 Scene 종류가 되는 스크립트(📜GameScene 혹은 📜LoginScene) 붙임. 이 @Scene
는 동적으로 생성되는 존재가 아니게 할 것.
그리고 씬 전환을 하려면 씬들이 반드시 Build Setting 에 등록이 되어 있어야 한다.
로그인씬에서 아이디와 비밀번호 입력 후 이를 서버에 보내서 서버로부터 OK 사인을 받으면 이제 인게임 씬으로 넘어가는 이런식으로 구현하면 된다.
📜Define
public enum Scene
{
Unknown, // 디폴트
Login, // 로그인 화면 씬
Lobby, // 로비 씬
Game, // 인게임 씬
}
📜BaseScene
여러가지 종류의 씬들이 상속받을 스크립트. 즉, 씬들이 공통적으로 갖고 있을 부분 모음
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
public abstract class BaseScene : MonoBehaviour
{
public Define.Scene SceneType { get; protected set; } = Define.Scene.Unknown; // 디폴트로 Unknow 이라고 초기화
void Awake()
{
Init();
}
protected virtual void Init()
{
Object obj = GameObject.FindObjectOfType(typeof(EventSystem));
if (obj == null)
Managers.Resource.Instantiate("UI/EventSystem").name = "@EventSystem";
}
public abstract void Clear();
}
SceneType
- 이 씬은 어떤 타입의 씬인지를 알려줄 정보 (from 📜Define의
Scene
enum) - 자식 씬들에게 상속
- get 은 ScreenType 프로퍼티의 접근지정자 따라 public 하게, set 은 protected 한 프로퍼티로 설정
- 이 씬은 어떤 타입의 씬인지를 알려줄 정보 (from 📜Define의
- Init
- 가상 함수로 자식 씬들에서
base.Init()
으로 부분적으로 공통적으로 실행시켜야 하는 부분들을 정의- UI는 반드시
EventSystem
이 필요하기 때문에 꼭! 만들어주어야 한다.EventSystem
을 만들어주는 작업. -
EventSystem
도 그냥 프리팹으로 만들어버리고 이를 생성시키기
- UI는 반드시
- 가상 함수로 자식 씬들에서
- Clear
- 추상 함수로 Clear 내용은 전적으로 자식 씬들에게 맡김
- 자식들마다 다 각자의 다른 방식으로 오버라이딩
Start 대신 Awake 를 사용하는 이유
Awkae는 Start보다 먼저 실행되며, 스크립트가 꺼져있어도 실행된다. 오브젝트만 활성화되어 있다면!
이 Awake 는 자식들에게 상속된다.
📜 GameScene
“GameScene” 씬의
@Scene
오브젝트에 붙는다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameScene : BaseScene
{
protected override void Init() // 상속 받은 Awake() 안에서 실행됨. "GameScene"씬 초기화
{
base.Init(); // 📜BaseScene의 Init()
SceneType = Define.Scene.Game; // 📜GameScene의 씬 종류는 GameScene
Managers.UI.ShowSceneUI<UI_Inven>(); // 인벤토리 UI 생성
for (int i = 0; i < 5; i++) // 📜GameScene의 씬 초기화시 UnityChan 프리팹을 5개 생성한다!
Managers.Resource.Instantiate("UnityChan");
}
public override void Clear()
{
}
}
📜 LoginScene
“LoginScene” 씬의
@Scene
오브젝트에 붙는다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class LoginScene : BaseScene
{
protected override void Init() // 상속 받은 Awake() 안에서 실행됨. "LoginScene"씬 초기화
{
base.Init();
SceneType = Define.Scene.Login; // 📜LoginScene의 씬 종류는 LoginScene
List<GameObject> list = new List<GameObject>();
for (int i = 0; i < 5; i++)
list.Add(Managers.Resource.Instantiate("UnityChan"));
foreach (GameObject obj in list)
{
Managers.Resource.Destroy(obj);
}
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.Q))
{
Managers.Scene.LoadScene(Define.Scene.Game);
}
}
public override void Clear()
{
Debug.Log("LoginScene Clear!");
}
}
- Update
Q
입력이 들어오면 📜SceneManagerEx(밑에 참고)의 LoadScene 함수로 “GameScene” 씬을 로드하도록 한다.
🚀 SceneManager
📜SceneManagerEx
이미 SceneManager 가 유니티엔진에 있기 때문에 Ex 붙여서 구분해줌..
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class SceneManagerEx
{
public BaseScene CurrentScene { get { return GameObject.FindObjectOfType<BaseScene>(); } }
string GetSceneName(Define.Scene type)
{
string name = System.Enum.GetName(typeof(Define.Scene), type); // C#의 Reflection. Scene enum의
return name;
}
public void LoadScene(Define.Scene type)
{
Managers.Clear();
SceneManager.LoadScene(GetSceneName(type)); // SceneManager는 UnityEngine의 SceneManager
}
public void Clear()
{
CurrentScene.Clear();
}
}
CurrentScene
는 그저 GameObject.FindObjectOfType<BaseScene>(); 리턴 값을 받으면 땡! 📜GameScene 혹은 📜LoginScene이 할당 될 것이다. 둘 다 📜BaseScene의 자식들이기 때문에.
📜Manager
SceneManagerEx _scene = new SceneManagerEx();
public static SceneManagerEx Scene { get { return Instance._scene; } }
🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄
댓글 남기기