
유니티에서 다른 씬으로 넘어가려면 UnityEngine.SceneManagement 의 SceneManager.LoadScene 에 씬 이름을 넣습니다. 넘어갈 씬은 미리 Scene List(예전 Build Settings 창의 Scenes In Build)에 들어 있어야 하고, 로딩 바를 보여 주려면 LoadSceneAsync 로 바꿔 progress 를 읽습니다.
using UnityEngine.SceneManagement;
SceneManager.LoadScene("Game"); // 이름으로
타이틀 화면에서 시작 버튼을 누르면 게임 화면으로, 게임이 끝나면 결과 화면으로 넘어가는 것처럼 화면을 통째로 바꿀 때는 씬을 나눠 두고 SceneManager 로 불러옵니다. 그런데 처음 해 보면 「씬을 찾을 수 없다」 는 오류가 나거나, 씬이 큰 경우 버튼을 누른 뒤 화면이 잠깐 멈춘 것처럼 보이기도 합니다. 이번 글에서는 이름으로 바로 넘어가는 LoadScene 과, 뒤에서 읽으면서 로딩 바를 채우는 LoadSceneAsync 를 버튼 두 개에 나눠 단 SceneLoader 를 만들겠습니다. 씬 이름을 잘못 적었을 때 오류 대신 경고만 남기고 멈추는 확인과, 버튼을 두 번 눌러도 한 번만 불러오게 막는 처리도 함께 넣었습니다.
C# (UNITY 3D)
button_load 를 누르면 다음 프레임에 바로 Game 씬으로 넘어갑니다. button_load_async 를 누르면 로딩 화면이 켜지고, 씬을 읽는 동안 로딩 바와 % 글자가 0% 에서 100% 까지 차오른 뒤 넘어가는 예시입니다. 씬 이름이 Scene List 에 없으면 어느 버튼이든 넘어가지 않고 Console 에 경고만 남깁니다.
1. 준비 — 씬을 Scene List 에 넣기
File > Build Profiles 를 열고 Scene List 에 시작 씬(예: Title)과 넘어갈 씬(예: Game)을 끌어다 넣습니다. 예전 버전에서는 File > Build Settings 의 Scenes In Build 입니다. 목록 맨 위가 0번이고 앱을 켜면 처음 열리는 씬입니다. 체크가 꺼진 씬은 빌드에 들어가지 않습니다.
using System;
using System.Collections;
using System.IO;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
SceneManager 와 SceneUtility 는 UnityEngine.SceneManagement 에, 로딩 바 Image 와 Button 은 UnityEngine.UI 에, % 글자 TMP_Text 는 TMPro 에 있습니다. System.IO 는 씬 경로에서 이름만 떼어 낼 때 씁니다.
Title 씬의 빈 오브젝트에 SceneLoader 를 붙이고 인스펙터에서 scene_name 에 Game 을 적은 뒤, 버튼 두 개 · 로딩 화면 패널 · 로딩 바 Image · % 글자를 끌어다 넣습니다. 로딩 바 Image 는 Image Type 을 Filled 로 두어야 fillAmount 로 채워집니다.
2. 씬 전환 · 로딩 바 코드
using System;
using System.Collections;
using System.IO;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
//CodeFinder 코드파인더
//From https://codefinder.janndk.com/
public class SceneLoader : MonoBehaviour
{
public string scene_name = "Game"; // 넘어갈 씬 이름(Scene List 에 들어 있어야 함)
public Button button_load; // 바로 넘어가기
public Button button_load_async; // 로딩 바를 보며 넘어가기
public GameObject panel_loading; // 로딩 화면(처음엔 꺼 둠)
public Image image_bar; // 로딩 바(Image Type : Filled)
public TMP_Text text_percent; // 몇 % 인지
bool is_loading; // 두 번 누르기 막기
void Start()
{
if (panel_loading != null)
panel_loading.SetActive(false);
if (button_load != null)
{
button_load.onClick.RemoveAllListeners();
button_load.onClick.AddListener(Load_Scene);
}
if (button_load_async != null)
{
button_load_async.onClick.RemoveAllListeners();
button_load_async.onClick.AddListener(Load_SceneAsync);
}
}
public void Load_Scene()
{
if (is_loading || !Can_Load(scene_name))
return;
is_loading = true;
SceneManager.LoadScene(scene_name); // 다음 프레임에 바로 넘어감
}
public void Load_SceneAsync()
{
if (is_loading || !Can_Load(scene_name))
return;
is_loading = true;
StartCoroutine(Load_Routine(scene_name));
}
public static bool Can_Load(string name)
{
for (int i = 0; i < SceneManager.sceneCountInBuildSettings; i++)
{
string path = SceneUtility.GetScenePathByBuildIndex(i); // 예 : Assets/Scenes/Game.unity
if (string.Equals(Path.GetFileNameWithoutExtension(path), name, StringComparison.OrdinalIgnoreCase)) // 씬 이름은 대소문자를 안 가림
return true;
}
Debug.LogWarning("씬 " + name + " 이 Scene List 에 없습니다");
return false;
}
IEnumerator Load_Routine(string name)
{
if (panel_loading != null)
panel_loading.SetActive(true);
Show_Progress(0f);
AsyncOperation op = SceneManager.LoadSceneAsync(name);
op.allowSceneActivation = false; // 다 읽어도 넘어가지 말고 기다림
while (op.progress < 0.9f) // 기다리는 동안 progress 는 0.9 에서 멈춤
{
Show_Progress(op.progress / 0.9f);
yield return null;
}
Show_Progress(1f);
yield return new WaitForSeconds(0.2f); // 100% 를 잠깐 보여 줌
op.allowSceneActivation = true; // 이제 넘어감
}
public void Show_Progress(float value)
{
value = Mathf.Clamp01(value);
if (image_bar != null)
image_bar.fillAmount = value;
if (text_percent != null)
text_percent.text = Mathf.RoundToInt(value * 100f) + "%";
}
}
LoadScene 은 부르자마자가 아니라 다음 프레임에 씬을 바꿉니다. LoadSceneAsync 는 씬을 뒤에서 읽으면서 AsyncOperation 을 돌려주고, 그 progress 로 얼마나 읽었는지 알 수 있습니다. allowSceneActivation 을 false 로 두면 다 읽어도 progress 가 0.9 에서 멈춘 채 기다리기 때문에, 로딩 바는 progress 를 0.9 로 나눠 0~1 로 바꿔 채우고, 100% 를 잠깐 보여 준 뒤 true 로 바꿔 넘어갑니다. 넘어가기 전에 버튼을 또 누르면 같은 씬을 두 번 불러오게 되므로 is_loading 으로 막았습니다.
Can_Load 는 Scene List 에 있는 씬의 경로를 하나씩 꺼내 파일 이름만 떼어 비교합니다. Unity 문서에 씬 이름은 대소문자를 가리지 않는다고 되어 있어서 비교도 대소문자를 무시하게 맞췄습니다.
이 스크립트는 Unity 6000.6.3f1 에서 컴파일 오류 없이 들어갔고, 배치 모드에서 Start 를 불러도 예외가 없었습니다. 배치 모드는 플레이 모드가 아니라서 실제로 씬이 넘어가는 장면까지는 보지 못했고, Scene List 확인과 로딩 바 계산 값만 직접 넣어 확인했습니다(3절).
변수(variable)
scene_name(string) : 넘어갈 씬 이름
button_load(Button) : 바로 넘어가는 버튼
button_load_async(Button) : 로딩 바를 보며 넘어가는 버튼
panel_loading(GameObject) : 로딩 화면
image_bar(Image) : 로딩 바(Filled)
text_percent(TMP_Text) : % 글자
is_loading(bool) : 이미 불러오는 중인지
함수(function)
Start : 로딩 화면을 끄고 두 버튼에 Load_Scene · Load_SceneAsync 를 연결합니다.
Load_Scene : 씬이 목록에 있으면 LoadScene 으로 바로 넘어갑니다.
Load_SceneAsync : 씬이 목록에 있으면 Load_Routine 코루틴을 시작합니다.
Can_Load : Scene List 에 그 이름의 씬이 있는지 대소문자 없이 찾고, 없으면 경고를 남깁니다.
Load_Routine : LoadSceneAsync 로 읽으면서 로딩 바를 채우고, 다 읽으면 넘어갑니다.
Show_Progress : 0~1 값을 로딩 바 fillAmount 와 % 글자로 보여 줍니다.
3. 넣어 본 값으로 보기

Scene List 에 Title 과 Game 을 넣고 확인하니 Game 과 game 은 찾았고, 철자를 틀린 Gmae 와 목록이 비었을 때는 False 가 나와 넘어가지 않았습니다. 로딩 바는 progress 0.45 에서 50%, 0.9 에서 100% 가 되었고, 범위 밖의 값은 Clamp01 로 0% · 100% 에 묶였습니다.
4. 번호로 · 다시 시작 · 겹쳐 열기
SceneManager.LoadScene(1); // Scene List 의 번호로
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex); // 지금 씬 다시 시작
SceneManager.LoadScene("Pause", LoadSceneMode.Additive); // 지금 씬 위에 하나 더 얹기
이름 대신 Scene List 의 번호를 넣어도 됩니다. 다만 목록 순서를 바꾸면 번호도 바뀌므로 이름이 더 안전합니다. 게임 오버 뒤 「다시 하기」 는 지금 씬의 buildIndex 를 다시 불러오면 처음 상태로 돌아갑니다. LoadSceneMode.Additive 를 주면 지금 씬을 닫지 않고 그 위에 다른 씬을 함께 열어서, 일시정지 화면처럼 따로 만든 씬을 겹쳐 보여 줄 때 씁니다.
5. 안 넘어갈 때 — 자주 하는 실수
Scene List 에 안 넣었다
씬 파일이 프로젝트에 있어도 Scene List 에 없으면 불러올 수 없습니다. 이 글의 Can_Load 는 이때 경고만 남기고 멈추지만, LoadScene 을 바로 부르면 씬을 찾을 수 없다는 오류가 납니다.
로딩 바가 90% 에서 멈춘다
allowSceneActivation 을 false 로 두면 progress 는 0.9 에서 멈추고 isDone 도 true 가 되지 않습니다. 「progress 가 1 이 되면 넘어가기」 처럼 짜면 영원히 기다리게 되니, 0.9 에 닿았는지로 보고 allowSceneActivation 을 true 로 바꿔야 합니다.
넘어가면 앞 씬의 오브젝트가 사라진다
LoadScene 은 기본으로 지금 씬을 닫고 새 씬을 엽니다. 배경음악이나 점수처럼 씬을 넘어서도 남아야 하는 것은 DontDestroyOnLoad 로 따로 남기거나 PlayerPrefs 같은 곳에 저장해 두어야 합니다.
에디터 스크립트에서 부르면 오류가 난다
SceneManager.LoadScene · LoadSceneAsync 는 플레이 중에만 됩니다. 이 글을 확인한 배치 모드(플레이 모드 아님)에서 부르니 「This can only be used during play mode」 라는 InvalidOperationException 이 났습니다. 에디터에서 씬을 여는 도구를 만들 때는 EditorSceneManager.OpenScene 을 씁니다.
함께 보기: 로딩 바를 채우는 fillAmount 는 유니티 Image.fillAmount 로 쿨타임 · 로딩 바 만들기, 버튼에 함수를 코드로 다는 법은 유니티 Button onClick 코드로 연결 · interactable 로 잠금 에 있습니다.
씬 불러오기 동작은 Unity 공식 문서 SceneManager.LoadScene · SceneManager.LoadSceneAsync · AsyncOperation.allowSceneActivation 과 Unity 6000.6.3f1 에디터(Windows)에서 값을 넣어 본 결과를 기준으로 적었습니다.
'Unity3D > C#' 카테고리의 다른 글
| 유니티 노치 화면 대응 · 안전 영역 (Screen.safeArea) (0) | 2026.10.31 |
|---|---|
| 유니티 안드로이드 뒤로가기 · 앱 종료 (KeyCode.Escape) (0) | 2026.10.30 |
| 유니티 앱 내릴 때 자동 저장 (OnApplicationPause) (0) | 2026.10.29 |
| 유니티 진동 울리기 · 진동 끄기 설정 (Handheld.Vibrate) (0) | 2026.10.28 |
| 유니티 프레임 60fps 고정 (targetFrameRate) (0) | 2026.10.27 |