07/23 장면 흐름 (Scene Flow) 구성 및 스크립팅

심지태
∙∙조회 13
07/23 장면 흐름 (Scene Flow) 구성 및 스크립팅

SceneManager

SceneManager는 게임 실행 중 Scene을 불러오고, 제거하고, 전환하는 정적 클래스입니다. Scene은 메뉴·스테이지·로딩 화면처럼 게임 공간을 나누는 단위이며, 사용하려면 using UnityEngine.SceneManagement;를 선언합니다. 불러올 Scene은 먼저 빌드의 Scene 목록에 등록해야 합니다. Unity 공식 문서

기능주요 코드용도
Scene 즉시 전환LoadScene("Game")현재 Scene에서 다른 Scene으로 전환
비동기 로딩LoadSceneAsync("Game")끊김을 줄이고 로딩 화면 구현
추가 로딩LoadSceneAsync("UI", LoadSceneMode.Additive)기존 Scene을 유지한 채 다른 Scene 추가
Scene 제거UnloadSceneAsync("UI")추가로 불러온 Scene 제거
활성 Scene 확인·변경GetActiveScene(), SetActiveScene()새 오브젝트가 생성될 Scene 및 조명 설정 기준 지정
로딩 완료 감지SceneManager.sceneLoadedScene 로딩 후 초기화 작업 실행

Scene 로딩 모드는 두 가지입니다. Single은 기존 Scene들을 제거하고 새 Scene 하나를 불러오는 기본 모드이고, Additive는 기존 Scene을 유지하면서 새 Scene을 겹쳐 불러옵니다. Additive로 불러온 Scene은 자동으로 활성 Scene이 되지 않으므로 필요하면 SetActiveScene()을 호출해야 합니다. 활성 Scene은 렌더링 여부가 아니라 새 GameObject의 소속과 조명 설정의 기준을 결정합니다.

arduino
using UnityEngine.SceneManagement;

// 일반적인 Scene 전환
SceneManager.LoadSceneAsync("GameScene", LoadSceneMode.Single);

실제 게임에서는 LoadScene()이 프레임 끊김을 일으킬 수 있어 대부분 LoadSceneAsync()가 권장됩니다. 음악·게임 매니저처럼 Scene이 바뀌어도 유지할 오브젝트는 DontDestroyOnLoad()를 사용하되, 중복 생성되지 않도록 싱글턴 등의 처리가 필요합니다. 또한 sceneLoaded 이벤트를 구독했다면 OnDisable()에서 반드시 구독을 해제하는 것이 안전합니다.

씬 로드 방법

scss
// Scene 이름으로 불러오기
SceneManager.LoadScene("GameScene");

// Scene 빌드 인덱스로 불러오기
// Enum을 사용하여 좀 더 안전하게 진행 가능
SceneManager.LoadScene(0);
  • Scene은 File → Build Profiles의 Scene List에 등록되어 있어야 합니다.
  • 빌드 인덱스는 0부터 시작하며 Scene List의 순서대로 정해집니다. -> Enum을 사용하여 좀 더 안전하게 진행 가능
  • 로딩 중 끊김을 줄이려면 실제 게임에서는 LoadSceneAsync()가 권장됩니다.

LoadScene과 LoadSceneAsync 비교

구분LoadSceneLoadSceneAsync
로딩 방식다음 프레임에 로딩을 완료하는 동기 방식백그라운드에서 비동기로 로딩
게임 화면로딩 중 멈춤이나 끊김이 발생할 수 있음로딩 중에도 화면·애니메이션 처리 가능
반환값없음(void)AsyncOperation 반환
진행률 확인불가능progress, isDone으로 확인 가능
주요 용도작은 Scene, 간단한 테스트큰 Scene, 로딩 화면이 필요한 실제 게임
권장도제한적으로 사용일반적으로 권장

강사님 꿀팁

csharp
using UnityEngine;

public abstract class SingletonBehavior<T> : MonoBehaviour where T : MonoBehaviour
{
    // 내부에서 사용하는 인스턴스
    private static T instance;

    // 외부로 접근점 열어둠
    public static T Instance
    {
        get
        {
            if (instance == null)
            {
                // 이미 씬에 배치되었는지 찾음.
                instance = FindAnyObjectByType<T>();

                // 씬에 없으면 생성
                if (instance == null)
                {
                    GameObject singleton = new GameObject(typeof(T).Name);
                    instance = singleton.AddComponent<T>();
                }
            }

            return instance;
        }
    }

    // 싱글톤 만들기
    protected virtual void Awake()
    {
        if (instance != null)
        {
            Destroy(gameObject);
            return;
        }

        instance = this as T;
        DontDestroyOnLoad(gameObject);
    }

    // 삭제되었을때 처리
    protected virtual void OnDestroy()
    {
        if (instance == this as T)
        {
            instance = null;
        }
    }
}

사용 예시

csharp
public class LoadSceneManager : SingletonBehavior<LoadSceneManager>

원리 더 보기: static은 어디에 살길래 살아남을까

구역사는 것수명
스택함수의 지역 변수함수가 끝나면 사라집니다
힙new로 만든 객체, Scene의 오브젝트들아무도 참조하지 않으면 정리됩니다
정적 영역static 변수프로그램 시작부터 종료까지