I'm creating a game called Gravity Shifter, and I currently have four scenes. The first one is the Main Menu, followed by PersistentScene, which contains UI elements such as buttons and health text, allowing the UI to persist across all levels. Then, I have Level1 and Level2.
As I mentioned, except for the Main Menu, I want PersistentScene to be present in all other scenes (the level scenes). However, when I play the game and press the restart button, the game restarts, but PersistentScene gets deleted. This shouldn't happen because, after restarting, I'm unable to use the UI elements.
Now I have some code that might be causing the problem.
GameManager.cs
:
using UnityEngine;
using UnityEngine.SceneManagement;
// bu kod persistentSceneyi gerekli levellere eklemek icin var.
public class GameManager : MonoBehaviour
{
public static GameManager instance;
void Awake()
{
// Eğer GameManager'ın bir örneği henüz yoksa, bu örneği kalıcı yap
if (instance == null)
{
instance = this;
DontDestroyOnLoad(gameObject); // Bu GameObject ve bileşenleri sahne geçişlerinde kalır.
}
else
{
// Zaten bir örnek varsa, bu fazladan olanı yok et.
Destroy(gameObject);
return;
}
}
void Start()
{
// PersistentScene zaten yüklenmemişse ve main menu sahnesinde degil isek o zaman yukleriz
if (!SceneManager.GetSceneByName("PersistentScene").isLoaded && SceneManager.GetActiveScene().name != "MainMenu")
{
SceneManager.LoadScene("PersistentScene", LoadSceneMode.Additive);
}
Time.timeScale = 1f; // Level1'e girerken zaman ölçeğini sıfırlıyoruz
}
// Oyunu sıfırlama fonksiyonu Oyun restart oldugunda bu funcu restart game button scriptin de kullanicaz
public void RestartGame()
{
// Zamanı normal hızda başlat oyun yeniden basladiginda bu deger 0 olursa oyun donar bunu engellemek icin de bunu 1 yapariz
Time.timeScale = 1f;
PlayerManager.Instance.ResetPlayerPosition();
}
}
PlayerManager.cs
:
using UnityEngine;
public class PlayerManager : MonoBehaviour
{
private 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.
}
}
public void ResetPlayerPosition()
{
if (player != null)
{
player.transform.position = startingPosition; // Oyuncuyu sıfırla
}
else
{
Debug.LogWarning("Player object is not assigned.");
}
}
// Oyuncuyu Don't Destroy'dan çıkar ve sil
public void RemovePlayerFromDontDestroy()
{
Destroy(gameObject);
}
}
RestartGameButton.cs
:
using UnityEngine;
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;
// Singleton üzerinden GameManager'a erişip RestartGame fonksiyonunu çağır
if (GameManager.instance != null)
{
GameManager.instance.RestartGame(); // GameManager üzerinden oyunu sıfırla
}
else
{
Debug.LogError("GameManager instance is not found!");
}
SceneLoader.LoadScene(2); // level1'i yuklemek icin
}
}
SceneLoader.cs
:
using UnityEngine;
using UnityEngine.SceneManagement;
public class SceneLoader : MonoBehaviour
{
public static GameObject backupCamera; // Yedek kamera referansı
private static string uiSceneName = "PersistentScene"; // UI'nin sahne adı
public static void LoadScene(int sceneIndex)
{
// Eğer ana menüye dönülüyorsa, tüm sahneleri temizle
if (sceneIndex == 1)
{
DestroyPersistentObjects();
SceneManager.LoadScene(sceneIndex);
}
else
{
// Yeni sahneyi yükle (UI kaybolmaz)
SceneManager.LoadScene(sceneIndex, LoadSceneMode.Single);
// Eğer UI sahnesi yüklü değilse yükle
if (!SceneManager.GetSceneByName(uiSceneName).isLoaded)
{
SceneManager.LoadScene(uiSceneName, LoadSceneMode.Additive);
}
// Yedek kamerayı aç
if (backupCamera != null)
{
backupCamera.SetActive(true);
}
}
}
// Bu sadece ana menüye dönüş için kullanılır
private static void DestroyPersistentObjects()
{
GameObject[] dontDestroyObjects = GameObject.FindObjectsOfType<GameObject>();
foreach (GameObject obj in dontDestroyObjects)
{
if (obj.scene.buildIndex == -1) // Eğer sahneye bağlı değilse (DontDestroyOnLoad)
{
Destroy(obj);
}
}
}
}
I want the PersistentScene to be present in every level scene except the Main Menu.
Thank you!
I'm creating a game called Gravity Shifter, and I currently have four scenes. The first one is the Main Menu, followed by PersistentScene, which contains UI elements such as buttons and health text, allowing the UI to persist across all levels. Then, I have Level1 and Level2.
As I mentioned, except for the Main Menu, I want PersistentScene to be present in all other scenes (the level scenes). However, when I play the game and press the restart button, the game restarts, but PersistentScene gets deleted. This shouldn't happen because, after restarting, I'm unable to use the UI elements.
Now I have some code that might be causing the problem.
GameManager.cs
:
using UnityEngine;
using UnityEngine.SceneManagement;
// bu kod persistentSceneyi gerekli levellere eklemek icin var.
public class GameManager : MonoBehaviour
{
public static GameManager instance;
void Awake()
{
// Eğer GameManager'ın bir örneği henüz yoksa, bu örneği kalıcı yap
if (instance == null)
{
instance = this;
DontDestroyOnLoad(gameObject); // Bu GameObject ve bileşenleri sahne geçişlerinde kalır.
}
else
{
// Zaten bir örnek varsa, bu fazladan olanı yok et.
Destroy(gameObject);
return;
}
}
void Start()
{
// PersistentScene zaten yüklenmemişse ve main menu sahnesinde degil isek o zaman yukleriz
if (!SceneManager.GetSceneByName("PersistentScene").isLoaded && SceneManager.GetActiveScene().name != "MainMenu")
{
SceneManager.LoadScene("PersistentScene", LoadSceneMode.Additive);
}
Time.timeScale = 1f; // Level1'e girerken zaman ölçeğini sıfırlıyoruz
}
// Oyunu sıfırlama fonksiyonu Oyun restart oldugunda bu funcu restart game button scriptin de kullanicaz
public void RestartGame()
{
// Zamanı normal hızda başlat oyun yeniden basladiginda bu deger 0 olursa oyun donar bunu engellemek icin de bunu 1 yapariz
Time.timeScale = 1f;
PlayerManager.Instance.ResetPlayerPosition();
}
}
PlayerManager.cs
:
using UnityEngine;
public class PlayerManager : MonoBehaviour
{
private 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.
}
}
public void ResetPlayerPosition()
{
if (player != null)
{
player.transform.position = startingPosition; // Oyuncuyu sıfırla
}
else
{
Debug.LogWarning("Player object is not assigned.");
}
}
// Oyuncuyu Don't Destroy'dan çıkar ve sil
public void RemovePlayerFromDontDestroy()
{
Destroy(gameObject);
}
}
RestartGameButton.cs
:
using UnityEngine;
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;
// Singleton üzerinden GameManager'a erişip RestartGame fonksiyonunu çağır
if (GameManager.instance != null)
{
GameManager.instance.RestartGame(); // GameManager üzerinden oyunu sıfırla
}
else
{
Debug.LogError("GameManager instance is not found!");
}
SceneLoader.LoadScene(2); // level1'i yuklemek icin
}
}
SceneLoader.cs
:
using UnityEngine;
using UnityEngine.SceneManagement;
public class SceneLoader : MonoBehaviour
{
public static GameObject backupCamera; // Yedek kamera referansı
private static string uiSceneName = "PersistentScene"; // UI'nin sahne adı
public static void LoadScene(int sceneIndex)
{
// Eğer ana menüye dönülüyorsa, tüm sahneleri temizle
if (sceneIndex == 1)
{
DestroyPersistentObjects();
SceneManager.LoadScene(sceneIndex);
}
else
{
// Yeni sahneyi yükle (UI kaybolmaz)
SceneManager.LoadScene(sceneIndex, LoadSceneMode.Single);
// Eğer UI sahnesi yüklü değilse yükle
if (!SceneManager.GetSceneByName(uiSceneName).isLoaded)
{
SceneManager.LoadScene(uiSceneName, LoadSceneMode.Additive);
}
// Yedek kamerayı aç
if (backupCamera != null)
{
backupCamera.SetActive(true);
}
}
}
// Bu sadece ana menüye dönüş için kullanılır
private static void DestroyPersistentObjects()
{
GameObject[] dontDestroyObjects = GameObject.FindObjectsOfType<GameObject>();
foreach (GameObject obj in dontDestroyObjects)
{
if (obj.scene.buildIndex == -1) // Eğer sahneye bağlı değilse (DontDestroyOnLoad)
{
Destroy(obj);
}
}
}
}
I want the PersistentScene to be present in every level scene except the Main Menu.
Thank you!
Share Improve this question edited 2 days ago DarkBee 15.6k8 gold badges70 silver badges115 bronze badges asked Feb 6 at 15:56 nuray nasirzadenuray nasirzade 12 bronze badges 2 |1 Answer
Reset to default 0In your RestartGameButton class just return after this line
GameManager.instance.RestartGame();
because after this line your code continues to this line
SceneLoader.LoadScene(2);
and this line is loading scene in index 2 in single mode which will remove all loaded scenes
But if you want to load the load scene on index 2 then you have to update your scene loader to hold a list of loaded scenes and unload loaded scenes first and then load new scenes and while doing this just exclude your PersistentScene scene
On top of this I would recommend you to watch this tutorial
AdditiveScene
, one of the issues with usingLoadSceneMode.Additive
is that whenever you load a different Scene usingLoadSceneMode.Single
it will destroy all the rest of the current active scenes and only load the passed scene references. A way of handling this is by usingSceneManager.UnloadScene
whenever you want to change to a different scene but maintain some of them in your active scene list. – Yeis Gallegos Commented Feb 7 at 0:57