Chapter 8. Scene Manager

Date:     Updated:

카테고리:

태그:

인프런에 있는 Rookiss님의 [C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part3: 유니티 엔진 강의를 듣고 정리한 필기입니다. 😀
🌜 강의 들으러 가기 Click

Chapter 8. Scene Manager

🚀 구조도

여태까지는 📜PlayerController에 Manager로부터 GameManager 스러운 일들을 실행시켰는데, 플레이어도 씬에 동적으로 생성되는 존재라면 📜PlayerController에 Manager를 호출하는 것은 바람직하지 않을 것이다. 게임 실행 中 내내 살아있는 선봉대 역할을 할 존재를 만들고 그에게 Manager를 호출하는 일을 맡겨야 한다. 이 선봉대 역할을 📜Scene 에서 할 것

  • 씬들. 각각 씬들만의 함수
    • 📜BaseScene
      • 📜GameScene
      • 📜LoginScene
  • 여러 씬들 한꺼번에 관리 👉 📜SceneManager

빈 오브젝트 @Scene 만들어서 그 곳에 Scene 종류가 되는 스크립트(📜GameScene 혹은 📜LoginScene) 붙임. 이 @Scene는 동적으로 생성되는 존재가 아니게 할 것.

image

그리고 씬 전환을 하려면 씬들이 반드시 Build Setting 에 등록이 되어 있어야 한다.

image

로그인씬에서 아이디와 비밀번호 입력 후 이를 서버에 보내서 서버로부터 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 한 프로퍼티로 설정
  • Init
    • 가상 함수로 자식 씬들에서 base.Init()으로 부분적으로 공통적으로 실행시켜야 하는 부분들을 정의
      • UI는 반드시 EventSystem이 필요하기 때문에 꼭! 만들어주어야 한다. EventSystem을 만들어주는 작업.
      • EventSystem도 그냥 프리팹으로 만들어버리고 이를 생성시키기

        image

  • 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; } }


🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우 
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄

맨 위로 이동하기

Unity Lesson 2 카테고리 내 다른 글 보러가기

댓글 남기기