개발자 사카
모바일 버전 씬 관리 본문
모바일 환경에서 씬을 변경하면 잠깐 멈추는 현상이 발생한다.
이를 위해서 가장 많이 쓰이는 방법이
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 클래스를 상속받는 클래스.
완벽하지는 않지만, 매 번 프로젝트 때나 새로운 기능이 생각나면 추가 및 수정하고 있다.
'Develop > Unity' 카테고리의 다른 글
모바일 화면을 항상 켜짐으로 설정하는 법 (0) | 2018.01.12 |
---|---|
IOException: Win32 IO returned ERROR_BROKEN_PIPE 에러가 떴을 때 (0) | 2018.01.12 |
입력한 텍스트가 이메일 형식인지 체크하는 방법 (2) | 2018.01.12 |
안드로이드 가상키보드에서 하얀 백그라운드에 하얀 글씨가 써져있을 때 (0) | 2018.01.12 |
2DSprite에 라이트 효과 주기 (0) | 2018.01.12 |