image.png

이 문제는 Unity의 씬 관리 시스템과 싱글톤 패턴 사이의 상호작용에서 발생하는 전형적인 이슈입니다. 자세히 분석해보겠습니다.

문제 발생 원리

1. DontDestroyOnLoad의 작동 방식

DontDestroyOnLoad(gameObject);

2. 참조 끊어짐 과정

  1. 씬 로드 전: GameManager.quiz → Scene의 Quiz 객체
  2. 씬 로드 중: Scene의 모든 객체 파괴 (Quiz, EndScreen 포함)
  3. 씬 로드 후: GameManager.quiz → null (참조 끊어짐)

3. 싱글톤의 역설

해결책들

해결책 1: 씬 로드 후 참조 재연결 (권장)

⇒ 단 QuizCanvas, WinCanvas 모두 On 상태여야 함!

using UnityEngine;
using UnityEngine.SceneManagement;

public class GameManager : MonoBehaviour
{
    public static GameManager Instance { get; private set; }

    [SerializeField] private Quiz quiz;
    [SerializeField] private EndScreen endScreen;

    void Awake()
    {
        if (Instance == null)
        {
            Instance = this;
            //DontDestroyOnLoad(gameObject);
        }
        else if (Instance != this)
        {
            Destroy(gameObject);
        }
    }

    void Start()
    {
        InitializeReferences();
        ShowQuizSceen();
    }

    void OnEnable()
    {
        SceneManager.sceneLoaded += OnSceneLoaded;
    }

    void OnDisable()
    {
        SceneManager.sceneLoaded -= OnSceneLoaded;
    }

    private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
    {
        InitializeReferences();
        ShowQuizSceen();
    }

    private void InitializeReferences()
    {
        if (quiz == null)
            quiz = Object.FindFirstObjectByType<Quiz>();
        if (endScreen == null)
            endScreen = Object.FindFirstObjectByType<EndScreen>();
    }

    private void ShowQuizSceen()
    {
        quiz.gameObject.SetActive(true);
        endScreen.gameObject.SetActive(false);
    }

    public void ShowEndSceen()
    {
        quiz.gameObject.SetActive(false);
        endScreen.gameObject.SetActive(true);
        endScreen.ShowFinalScore();
    }

    public void OnReplayLevel()
    {
        SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
    }
}

해결책 2: 모든 UI 요소도 DontDestroyOnLoad로 관리

void Awake()
{
    if (Instance == null)
    {
        Instance = this;
        DontDestroyOnLoad(gameObject);

        // UI 요소들도 함께 보존
        if (quiz != null)
            DontDestroyOnLoad(quiz.gameObject);
        if (endScreen != null)
            DontDestroyOnLoad(endScreen.gameObject);
    }
    else if (Instance != this)
    {
        Destroy(gameObject);
    }
}