You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity重启游戏时DontDestroyOnLoad场景玩家消失报错求助

问题描述

我正在开发一款名为Gravity Shifter的Unity游戏,重启游戏时,来自DontDestroyOnLoad场景的玩家对象消失,导致游戏报错并终止运行。游戏运行流程:GameManager从主菜单场景启动,点击开始按钮后进入Level1场景进行游戏。


PlayerManager.cs

using UnityEngine;

public class PlayerManager : MonoBehaviour
{
    public static PlayerManager instance;

    public static PlayerManager Instance
    {
        get { return instance; }
    }

    public GameObject player;
    public Vector3 startingPosition; // starting position when game restarts or starts

    private void Awake()
    {
        // Singleton yapısı
        if (instance == null)
        {
            instance = this;
            DontDestroyOnLoad(gameObject);  // PlayerManager, sahne geçişlerinde yok edilmez
        }
        else
        {
            Destroy(gameObject); // Aynı PlayerManager birden fazla sahnede varsa, yalnızca biri kalır.
        }
    }

    // bu playeri yeniden baslatir (restart veya level sceneleri gecisleri icin)
    public void RestartPlayer()
    {
        if (player != null)
        {
            Destroy(player);  // Eski player'ı sil
        }

        // Yeni player'ı oluştur ve başlat
        Instantiate(player, startingPosition, Quaternion.identity);
    }

    // Oyuncuyu Don't Destroy'dan çıkar ve sil (main menuye donerken cikartilir)
    public void RemovePlayerFromDontDestroy() 
    {
        Destroy(gameObject);
    }
}

GameManager.cs

using UnityEngine;
using UnityEngine.SceneManagement;

public class GameManager : MonoBehaviour
{
    public static GameManager instance;
    private NavMeshRebuilder navMeshRebuilder;

    [HideInInspector]
    public PlayerHealthUI playerHealthUI; // Tüm sahneler için ortak UI

    void Awake()
    {
        if (instance == null)
        {
            instance = this;
            DontDestroyOnLoad(gameObject);
            SceneManager.sceneLoaded += OnSceneLoaded; // Sahne yüklendiğinde çağrılacak
        }
        else
        {
            Destroy(gameObject);
            return;
        }
    }

    private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
    {
        if (scene.name != "MainMenu")
        {
            navMeshRebuilder = FindObjectOfType<NavMeshRebuilder>();
            RestartLighting();
        }
        else
        {
            navMeshRebuilder = null;
        }
    }

    void Start()
    {
        Time.timeScale = 1f;
    }

    private void RestartLighting()
    {
        DynamicGI.UpdateEnvironment();
        RenderSettings.ambientIntensity = 1f;
        LightmapSettings.lightmapsMode = LightmapsMode.CombinedDirectional;
    }

    public void RestartGame()
    {
        Debug.Log("RestartGame() çağrıldı!"); // Debug için ekledim

        PlayerManager.instance?.RestartPlayer();

        EnemyManager.instance?.ClearEnemies(); // Önce düşman listesini temizle
        EnemyManager.instance?.ResetEnemies();
        
        navMeshRebuilder?.RebuildNavMeshes();
        
        RestartLighting();

        Time.timeScale = 1f;
    }

    private void OnDestroy()
    {
        SceneManager.sceneLoaded -= OnSceneLoaded; // Hafıza sızıntısını önlemek için event'ten çık
    }
}

RestartGameButton.cs

using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

public class RestartGameButton : MonoBehaviour
{
    public GameObject backupCamera; // Yedek kamera referansı (Inspector'dan atanacak)
    public void RestartGameFromBeginning()
    {
        // Yedek kamerayı SceneLoader'a aktar
        SceneLoader.backupCamera = backupCamera;

        GameManager.instance.RestartGame();

        StartCoroutine(RestartCoroutine());
    }

    private IEnumerator RestartCoroutine()
    {
        yield return PersistentSceneLoader.instance.StartCoroutine(PersistentSceneLoader.EnsurePersistentSceneLoaded());

        yield return SceneLoader.instance.StartCoroutine(SceneLoader.LoadSceneCoroutine(2));
    }
}

SceneLoader.cs

using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;

public class SceneLoader : MonoBehaviour
{
    public static GameObject backupCamera;  // Yedek kamera referansı
    public static SceneLoader instance; // Singleton instance

    private void Awake()
    {
        if (instance == null)
        {
            instance = this;
        }
        else
        {
            Destroy(gameObject);
        }
    }

    public static void LoadScene(int sceneIndex)
    {
        instance.StartCoroutine(LoadSceneCoroutine(sceneIndex));
    }

    // LoadScene functionu oyuna ozel yapilmis sceneload yapan functur bu funcu leavegamebutton, restartbutton vb. leri icin olusturulmustur.
    public static IEnumerator LoadSceneCoroutine(int sceneIndex)
    {
        if (sceneIndex == 1) // MainMenu'ye dönüş
        {
            DestroyPersistentObjects();
            yield return PersistentSceneLoader.instance.StartCoroutine(PersistentSceneLoader.UnloadPersistentScene());
            SceneManager.LoadScene(sceneIndex);
        }
        else
        {
            yield return instance.StartCoroutine(UnloadAllLevels());

            yield return PersistentSceneLoader.instance.StartCoroutine(PersistentSceneLoader.EnsurePersistentSceneLoaded());

            yield return SceneManager.LoadSceneAsync(sceneIndex, LoadSceneMode.Additive);

            if (backupCamera != null)
            {
                backupCamera.SetActive(true);
            }
        }
    }

    private static IEnumerator UnloadAllLevels()
    {
        for (int i = 0; i < SceneManager.sceneCount; i++)
        {
            Scene scene = SceneManager.GetSceneAt(i);
            if (scene.name != "PersistentScene" && scene.name != "MainMenu")
            {
                yield return SceneManager.UnloadSceneAsync(scene);
            }
        }
    }

    private static void DestroyPersistentObjects()
    {
        GameObject[] dontDestroyObjects = GameObject.FindObjectsOfType<GameObject>();

        foreach (GameObject obj in dontDestroyObjects)
        {
            if (obj.scene.buildIndex == -1)
            {
                Destroy(obj);
            }
        }
    }
}

内容的提问来源于stack exchange,提问作者nuray nasirzade

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 06:30:55