유니티에는 씬을 불러오는 두 가지 방법이 있습니다.
동기 방식 - LoadScene
LoadScene (동기 방식): LoadScene은 동기 방식으로, 씬을 불러오는 동안 다른 작업을 수행하지 못합니다. 즉, 씬의 모든 데이터를 메모리로 가져오기 전까지 다른 작업이 중지됩니다. 불러오려는 씬의 규모가 크다면, 게임이 멈춰있는 상황이 더 지속될 수 있습니다.
씬의 크기가 작은 경우 LoadScene 방식을 사용하면 됩니다.
using UnityEngine;
using UnityEngine.SceneManagement;
public class Example : MonoBehaviour
{
public void LoadSceneExample()
{
SceneManager.LoadScene("SceneName");
}
}
비동기 방식 - LoadSceneAsync
LoadSceneAsync (비동기 방식): LoadSceneAsync는 비동기 방식으로, 씬을 불러오는 동안 다른 작업을 계속 수행할 수 있습니다.LoadSceneAsync 방식은 주로 코루틴을 사용하여 씬을 비동기적으로 불러옵니다.
LoadSceneAsync 방식에는 AsyncOperation 객체가 존재하여 비동기 작업의 상태를 추적할 수 있습니다.
프로퍼티 | 설명 |
allowSceneActivation | 이 프로퍼티는 씬이 준비되는 즉시 활성화될 것인지를 제어합니다. 기본값은 true이며, 이 경우 씬이 준비되는 즉시 활성화됩니다. false로 설정하면, 씬이 준비되더라도 활성화되지 않습니다. |
isDone | 이 프로퍼티는 비동기 작업이 완료되었는지를 나타냅니다. true이면 작업이 완료되었음을 의미하며, false이면 작업이 아직 완료되지 않았음을 의미합니다. |
progress | 이 프로퍼티는 비동기 작업의 진행 상황을 나타냅니다. 0.0에서 1.0 사이의 값을 가지며, 1.0은 작업이 완료되었음을 의미합니다. 이 값을 사용하여 로딩 바를 구현할 수 있습니다. |
씬의 크기가 큰 경우 LoadSceneAsync 방식을 사용하면 됩니다.
using UnityEngine.SceneManagement;
IEnumerator LoadSceneAsync(string sceneName)
{
AsyncOperation asyncOper = SceneManager.LoadSceneAsync(sceneName);
while (!asyncOper.isDone)
{
yield return null;
}
}
예시 코드 - 세팅
LoadSceneAsync방식을 이용한 코드를 만들어보았습니다.
세팅은 위 사진 처럼 해주시면 됩니다.
using System.Collections;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.Serialization;
using UnityEngine.UI;
public enum SceneName
{
MainMenu = 0,
MainGame,
}
public class SceneController : MonoBehaviour
{
public static SceneController Instance;
[SerializeField] private GameObject sceneLoadingPanel;
[SerializeField] private Image progressImage;
[SerializeField] private TextMeshProUGUI progressText;
[SerializeField] private float delay = 0.5f;
[SerializeField] private SceneName currentScene;
[SerializeField] private SceneName nextScene;
private void Awake()
{
Instance = this;
DontDestroyOnLoad(gameObject);
}
[ContextMenu("Test")]
public void Test()
{
LoadScene(nextScene);
}
private void OnGUI()
{
if (GUI.Button(new Rect(50, 10, 150, 50), "LoadScene"))
{
LoadScene(nextScene);
}
}
public void ReloadScene()
{
sceneLoadingPanel.SetActive(true);
StartCoroutine(LoadSceneAsync(currentScene));
}
public void LoadScene()
{
sceneLoadingPanel.SetActive(true);
StartCoroutine(LoadSceneAsync(nextScene));
}
public void LoadScene(SceneName sceneName)
{
sceneLoadingPanel.SetActive(true);
StartCoroutine(LoadSceneAsync(sceneName));
}
private IEnumerator LoadSceneAsync(SceneName sceneName)
{
currentScene = sceneName;
AsyncOperation asyncOper = SceneManager.LoadSceneAsync((int)sceneName);
asyncOper.allowSceneActivation = false;
float progress = 0f;
while (!asyncOper.isDone)
{
progress = Mathf.Lerp(progress, asyncOper.progress, 0.95f);
progressImage.fillAmount = progress;
progressText.text = Mathf.RoundToInt(progress * 100) + "%";
if (asyncOper.progress >= 0.9f)
{
yield return new WaitForSeconds(delay);
sceneLoadingPanel.SetActive(false);
asyncOper.allowSceneActivation = true;
}
yield return null;
}
}
}
using UnityEngine;
public class NextSceneTest : MonoBehaviour
{
public void Test()
{
SceneController.Instance.LoadScene(SceneName.MainGame);
}
}