씬을 로딩한 이후의 작업을 시키려고 다음과 같이 코드를 짜면 의도한 바 대로 작동하지 않는다.
SceneManager.LoadScene("LoginScene");
Manager.Net.roomManager = FindObjectOfType<RoomManager>();
Manager.Net.roomManager.RoomReInit();
LoadScene 이후에 작성된 코드들은 무시될 수 있다. 이후에 바로 코드에 명령어를 추가하면, roomManager가 null이 된다.
SceneManager.LoadScene("LoginScene") 이후 코드는 즉시 실행된다.LoadSceneAsync와 다르게 비동기적으로 처리되지 않고 한 프레임 뒤에 완료된다. 해당 프레임에서는 코드 수행 시작과 함께 다음 줄의 코드로 넘어간다.LoadScene()이 호출되면 현재 프레임 끝에 다음 씬으로 전환되고, 그 전에 바로 다음 줄이 실행돼서 FindObjectOfType<RoomManager>() 는 null이 되는 것이다.이 문제를 해결하려면, 씬을 비동기로 로드해오고 작업이 완료 됐을 때의 이벤트에 수행할 내용을 넣어야 한다.
private void ChangeToLoginScene()
{
AsyncOperation async = SceneManager.LoadSceneAsync("LoginScene");
if (async != null)
async.completed += (AsyncOperation op) =>
{
Manager.Net.roomManager = FindObjectOfType<RoomManager>();
Manager.Net.roomManager.RoomReInit();
};
}
yield return null을 하게 되면, 한 프레임을 넘어가는 것을 이용한 방법이다.StartCoroutine(LoadSceneAndInit());
IEnumerator LoadSceneAndInit()
{
SceneManager.LoadScene("LoginScene");
yield return null; // 한 프레임 대기 (씬이 완전히 전환됨)
Manager.Net.roomManager = FindObjectOfType<RoomManager>();
Manager.Net.roomManager.RoomReInit();
}
void Start()
{
SceneManager.sceneLoaded += OnSceneLoaded; // 구독 등록
SceneManager.LoadScene("LoginScene");
}
void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
if (scene.name == "LoginScene")
{
Manager.Net.roomManager = FindObjectOfType<RoomManager>();
Manager.Net.roomManager.RoomReInit();
SceneManager.sceneLoaded -= OnSceneLoaded; // 구독 해제
}
}