Notice
Recent Posts
Recent Comments
Link
«   2024/04   »
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 30
Archives
Today
Total
관리 메뉴

개발자 사카

모바일 버전 씬 관리 본문

Develop/Unity

모바일 버전 씬 관리

DevSaka 2018. 1. 12. 19:04

모바일 환경에서 씬을 변경하면 잠깐 멈추는 현상이 발생한다.


이를 위해서 가장 많이 쓰이는 방법이 


1. 한 씬에 모든걸 로드해놓고 카메라 위치를 변경한다.


2. 한 씬에 모든걸 로드해놓고 온/오프로 오브젝트를 관리한다.


필자는 후자의 방식을 애용하는 편이다. 스크립트만 잘 짜놓으면 오브젝트 온오프는 함수 한번으로 가능해지고, 


카메라 위치까지 신경쓸 필요가 없기 때문이다.


예를 들어 SceneManager 라는  오브젝트 안에 TitleScene, MainScene, PlayScene 등의 게임오브젝트들을 하위에 두고 필요할 때마다 그 씬만 켜두고 나머지 오브젝트느 켜두는 방식있다.


여기서 조금 관리하기 편하게 매니저 클래스를 작성해서 Scene 오브젝트를 삽입/삭제가 편하게 만들었다.  



<GameManager.cs>

public class GameManager : Monobehavior

{

public static GameManager gameMgr = null;

[SerializeField]

private SceneManager sceneMgr;

[SerializeField]

private SoundManager soundMgr;

[SerializeField]

private UIManager uiMgr;

// 게임매니저 클래스를 싱글톤으로 만든다.

void Awake()

{

if(gameMgr == null) gameMgr = this;

else if(gameMgr != this) Destroy(this.gameObject);

Initialize();

}

// 게임 시작 시 초기화는 여기서 이루어진다.

void Initialize() 

{

Screen.SetResolution(1280, 720, true); // 화면 해상도를 1280 * 720에 FullScreen으로 설정

Screen.sleepTimeout = SleepTimeout.NeverSleep; // 화면이 항상 켜짐을 유지하도록 설정

uiMgr.Initialize();

sceneMgr.Initialize();

soundMgr.Initialize();

}

// 모든 업데이트는 여기서 이루어진다.

void Update()

{

sceneMgr.Updated();

}

}


- 매니저 클래스이므로 싱글톤 구조를 사용했다.


- 전체 코드를 통틀어서 Awake, Update가 쓰여진 유일한 클래스다. 


- 좋은 구조라고 말할 순 없겠지만, 적어도 내가 짠 코드 순서정도는 내가 직접 관리하기가 편했다. 



<SceneManager.cs>

public enum SceneState { TITLE, MAIN, PLAY, }

public class SceneManager : Monobehavior

{

public static SceneManager sceneMgr = null;

[SerializeField]

private Scene[] scenes; // 씬들을 담을 변수

private Scene curScene; // 현재 실행 중인 씬

private SceneState curState;         // 현재 씬의 상태가 무슨 씬인지 알려줌

// 초기화

public void Initialize()

{

if(sceneMgr == null) sceneMgr = this;

else if(sceneMgr != this) Destroy(this.gameObject);

ChangeScene(SceneState.Main);

}

// 업데이트

public void Updated()

{

if(curScene.GetRunning()) curScene.Updated();

}

/// <summary>

/// 씬을 변경할 때 쓸 함수.

/// </summary>

/// <param name = "state"> 변경하고 싶은 씬의 상태 </param>

public void ChangeScene(SceneState state)

{

// 만약 바꿀 씬이 현재 씬과 같다면 종료

if(scenes[(int)state] == curScene) return;

// 현재 씬이 null이 아니라면 Exit() 함수 호출

if(curScene != null) curScene.Exit();

for(int i = 0; i < scenes.Length; i++)

{

if(i == (int)state)

{

curState = state;

scenes[i].gameObject.SetActive(true);

UIManager.uiMgr.SetUI(i, true);

curScene = scenes[(int)curState];

curScene.Initialize();

}

else

{

scenes[i].gameObject.SetActive(false);

UIManager.uiMgr.SetUI(i, false);

}

}

}

}

- 먼저 Enum으로 각 씬의 이름을 저장해서 가독성을 높였다. 이 클래스 역시 매니저 클래스이기 때문에 싱글톤.


- 업데이트 함수에서는 현재 씬의 업데이트만 돌린다.


- ChangeScene : 현재 씬에서 다음 씬으로 이동할 때 쓰는 함수이다. 현재 씬의 종료 시에 호출되는 Exit 함수를 호출해주고, 다음 씬의 초기화를 해준다.



<Scene.cs>

public class Scene : Monobehavior

{

private bool b_Running = false;


public virtual void Initialize() {}

public virtual void Updated() {}

public virtual void Exit() {}


public bool GetRunning() { return b_Running; }

public void SetRunning(bool Value) { b_Running = value; }

}


- 모든 씬 클래스는 이 클래스를 상속받는다. 

- b_Running으로 업데이트를 돌리고 싶을 때만 돌릴 수 있도록 했다.

- 초기화, 업데이트, 종료 후에 호출되는 함수를 virtual로 두고, 오버라이딩을 한다.


<SceneTemplate.cs>

public class SceneTemplate : Scene

{

public override void Initialize()

{

// 초기화할 내용

}

public override void Updated() 

{

// 업데이트에 들어갈 내용

}

public override void Exit()

{

// 종료 시에 호출될 내용

}

}


- Scene 클래스를 상속받는 클래스. 




완벽하지는 않지만, 매 번 프로젝트 때나 새로운 기능이 생각나면 추가 및 수정하고 있다.




Comments