Destroying Don't Destroy on Load

No. All of my sounds are based on how Rick taught “Laser Defender”. I really have no clue why that’s not working, why my Tile_Vainia coins are disappearing, & a few other things in my “Laser Defender Plus” game.
I try to spend at least 90 minutes figuring out the destroy the dontDestroyOnLoad thing.
So when I mess with the script @Nina sent me I get repeating stages that move slower & slower after I collide with the exit script (from Tile_Vainia).
Once I get that script working I’ll be able to publish a game I’ll be proud of.
Infact I don’t even know what an AudioListener is I only know how to use AudioSource.

Well that error you mentioned means there are multiple audio listeners in the scene, when you can only have one. Like most things in Unity, it’s a component.

I’m guessing you’re feeling a little overwealmed by Unity? Don’t worry, many do. And even when you think you’ve got it all figured out, something comes along and smacks you in the face. Forever learning. At least you’re sticking with it. It’ll be worth it when enough pieces fall into place.

Every time someone points you at a component, a term or a phrase you don’t understand, I want you to go and google it. If you find out it’s a component, try playing with it. Add it to a GameObject and see what it does. Maybe even write some code to see if you can interact with it in code. Whether it goes good or bad, it doesn’t matter. It’s a learning experience. Look at the Unity Docs and figure out how it works. If that doesn’t shed any light for you, go to youtube for a video or another source, like a forum.

This will occasionally send you down a rabbit hole. Sometimes you’ll get to the end and you’re more confused when you started, but those times it doesn’t, those pennies that drop into place make it worth it. The more you do stuff like this, the more you’ll learn and the faster your learning will snowball. You might not understand everything the first time around, but everytime you learn a piece of the puzzle, the other pieces become easier to learn and previous pieces become clearer.

Another technique I’d like you to try (until you feel you’ve got the hang of it) is to watch a video through without typing any code. Get a look at it. See what’s happening. Try to learn by observing. You might need to watch a few videos, or even a section. When you think you know what’s going on, then go back and type in the code. I’m not sure this will work for you, but when learning, so many can’t see the forest for the trees.

Also consider doing a bunch more courses. There’s heaps of them out there. I’ve completed a stupid amount of them during covid, not to mention the collection of half finished courses. Not to mention heaps of unfinished games/prototypes. Keep at it.

1 Like

This sounds as if there might be an endless loop. Maybe a new scene gets loaded over and over again. Maybe each of the scene contains a persistent game object. Maybe one of those persistent game objects is the camera with the AudioListener.

If you just copied and pasted the example code, you should have seen the Debug.Log messages from the example in your console. The example code does not load or modify anything, so it should not make your game slower.

So I been working at this as usual a min of 90 min per day. Then I looked at Rick’s “Laser Defender” 2018. What I don’t understand is (I have to describe sorry):
When I play Rick’s Laser Defender & Block Breaker 2018 the score text (& health text) is where is belongs & flows from stage to stage. Then in the game over carries over to show the player his/her score. Then if I hit replay, the score (& health) reset due to this part of Rick’s code.
… private void SetUpSingleton()
{
int numberGameSessions = FindObjectsOfType().Length;
if (numberGameSessions > 1)
{
Destroy(gameObject);
}
else
{
DontDestroyOnLoad(gameObject);
}
}…
Then here is the part where I don’t understand but will solve my problem. When I go to the main menu the score text disappears even though it’s part of dontDestroyOnLoad. This is actually better then what I was trying to do but my problem is I don’t understand why that happens I don’t know what screenshots or scrips I could show you to show you what the problem is because I don’t know. But if I could do that it would be better then what I wanted to do & I could focus on other aspects of “Laser Defender Plus”.

Hmmm so I also see:
… public void ResetGame()
{
Destroy(gameObject);
}
&
public void LoadGame()
{
SceneManager.LoadScene(“Game”);
FindObjectOfType().ResetGame();
}…
Are connected. I think I’m onto something.

Check if your “singleton” calls gameObject.SetActive(false); in the same if-block where Destroy(gameObject); gets called. If there isn’t that line of code, add it. Destroy() does not destroy immediately. FindObjectOfType could still find the “destroyed” game object.

When I go to the main menu the score text disappears even though it’s part of dontDestroyOnLoad.

Does it get destroyed or does it just contain an empty string? It is still possible to destroy “DontDestroyOnLoad” objects with the Destroy method.

Do you understand the concept of a singleton? If so, and if you feel that Rick’s singleton implementation causes unsolvable problems with your own ideas, you could try to replace it with another singleton version (first version, remove the sealed keyword, replace Singleton with your classname). You are not obliged to keep his code. His code solves his problems, not necessarily yours.

I think I’m onto something.

Yes, the two methods are connected. In the LoadGame method, you could try to swap the two method calls to ensure that ResetGame gets executed. Maybe LoadScene terminates the LoadGame method early and prevents ResetGame from being called in your case.


See also:

I know very little about Singletons. But what I’ll do is search for videos on it. Are there any that you would suggest because I’m sure there’s thousands?
I tried this with Laser Defender (base) but I need to test it with TileVainia & Shape (not block) Breaker.
If this works I can have the game done this week & then ask you guys for help posting I assume the webex or whatever it’s called version.
Ohhh I just noticed a link you sent me I’ll read it now.
Thank you.

Well, the purpose of a singleton is to ensure that there is only one object of a kind. That’s all.

In Unity, we do not have a real singelton because all objects in the Hierarchy get created. We need to destroy the superfluous ones. That’s not the actual singleton pattern because our code does not and cannot prevent the superfluous objects from being created in the first place. So Rick’s code is rather a “singleton”.

Another typical “singleton” version in Unity is this (plus the implementation for checking in which scene we are when a new scene gets loaded, and we destroy the game object if we are not in the “correct” scene):

using UnityEngine;
using UnityEngine.SceneManagement;

public class Singleton : MonoBehaviour
{
    static Singleton instance = null;
    int startingSceneIndex;

    void Start()
    {
        if (!instance)
        {
            instance = this;
            SceneManager.sceneLoaded += OnSceneLoaded;
            startingSceneIndex = SceneManager.GetActiveScene().buildIndex;
            DontDestroyOnLoad(gameObject);
        }
        else if (instance != this)
        {
            Destroy(gameObject);
        }
    }

    void OnSceneLoaded(Scene scene, LoadSceneMode mode)
    {
        if (startingSceneIndex != SceneManager.GetActiveScene().buildIndex)
        {
            instance = null;
            SceneManager.sceneLoaded -= OnSceneLoaded;
            Destroy(gameObject);
        }
    }
}

Theoretically, if you copied and pasted the code example from the Unity API, your current code should look similar to this (minus the “singleton”).

this refers to the current instance/object.

So what I learned about gameDev is solve on problem & create 2-3 more but somehow we enjoy this. Anyway do you have any idea why my ScenePercist.cs labeled items are not there anymore? Meaning my Tile_Vainia coins appear on my screen but not in my game levels.

Nevermind on that. I still have the scene persict but the dontdestroyonload is still not right. I want to focus on that.

That’s a good description of game development. :wink:

Meaning my Tile_Vainia coins appear on my screen but not in my game levels.

What do you mean by “on my screen”? In the Scene window but not in the Game window? If the coins are in the Hierarchy during runtime, it might be that they are rendered behind another sprite. Check the z-positions and make sure your different layers (background, foreground, coins, etc.) do not share the same z-position.

I still have the scene persict but the dontdestroyonload is still not right. I want to focus on that.

That’s a good idea. :slight_smile:

A little hint: The script I posted in my previous answer is what I used in the old version of the Tile Vania project to destroy the “persistent” coins that are supposed to get destroyed in other scenes but not in the current one. I just renamed the class so it is not that obvious.

Thanks Nina. I’m going to focus on what’s important. Rick teaches us to get the game working before the spice. I know you have a valuable hint but I’m going to do my research & work before I unlock what you say. This project has taught me that I need to be able to solve as many of my own problems, by myself as I can & yet there’s nothing wrong with asking for help after trying. Thanks for your help & not just giving me the answers but making me look for them & wrestle with Unity like Undertaker in hell in a cell.

A murder mystery where you’re the murderer, the detective and the victim, all at once.

@Nina
O.K. only focusing on the dontDestroyOnLoad thing. I have read the info you wrote in your reply, the link you sent me, other links & watched videos on singleton & I can honestly say I have no clue why you’re telling me to use a singleton. Most of the videos I’ve found is why developers hate singletons & why there’s almost never to be used.
I’ve also tried a lot of other things that seem to only work sometimes. My last attempt was trying to make the “Main Menu” command be a game reset that destroys any gameObj attached to it. I’m really not sure what to do next to get this game working let me show you my levels code.

…,using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class Levels : MonoBehaviour {

[SerializeField] float delayInSeconds = 2f;
public string sceneNameToLoad;
/* was original LD's Level.cs, is probably the best option for Scene loader template
 * Ends/GO = Game Over Stage. Con/Win = Congratulations Stages These are the stages in according to build setting:
 * 0 Splash, 1 Main Menu, 2 Numba Wizzy (intro, game, win), 5 Block Game Over, 6 Shape Breaker 6-9 (10 Congratz),
 11 Laser Def (12 Game over), 13 Text me, 14 Game over TileVainia, 15 Tilevainia (Level 1, 2, 3, 18 Game over)
19 Credits, 20 Justin (Game, CS, Delivery driver, 23 Congratz), 24 Game Over (open)
  ---FindObjectOfType<LaserSession>().ResetGame();---*/
public void LoadSplash()
{
    SceneManager.LoadScene(0);
}
 public void TextMe()
{
    SceneManager.LoadScene(13);
  
}

public void MainMenu()
{
//Loading Main Menu will destroy the gameObject even if dontDestroyOnLoad from any scene
SceneManager.LoadScene(1);
FindObjectOfType().ResetGame();
FindObjectOfType().KillMe();
Destroy(gameObject);
}
public void ShapeBreaker()
{
SceneManager.LoadScene(6);
}
public void Ace5000()
{
SceneManager.LoadScene(20);
}
public void NumWiz()
{
SceneManager.LoadScene(2);
}
public void TileVainia()
{
SceneManager.LoadScene(15);
}
public void LaserDef()
{
SceneManager.LoadScene(11);
}
public void Credits()
{
SceneManager.LoadScene(20);
}
public void GameOver()
{
SceneManager.LoadScene(24);
}
public void ShapeEnds()
{
SceneManager.LoadScene(5);
}
public void NextScene()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex + 1);
}
public void LaserEnds()
{
SceneManager.LoadScene(12);
} public void TileEnds()
{
SceneManager.LoadScene(14);
}
public void LoadThis()
{
SceneManager.LoadScene(sceneNameToLoad);
}

public void ResetGame()
{
    Destroy(gameObject);
}
public void LoadGameOver()
{
    StartCoroutine(WaitAndLoad());
}

IEnumerator WaitAndLoad()
{
    yield return new WaitForSeconds(delayInSeconds);
    SceneManager.LoadScene("Game Over");
}

public void QuitGame()
{
    Application.Quit();
}

}
/* This code works like this:

  • 1- Strings in other codes provide dontDestroyOnLoad for the necessary stages
  • 2- The Main Menu() has a destroy obj on it. To work this make sure the objects that are don’t
  • destroy on load will be destroy, put this script as the parent & the whole family will die
  • Check if your “singleton” calls gameObject.SetActive(false); in the same if-block where Destroy(gameObject);
  • gets called. If there isn’t that line of code, add it. Destroy() does not destroy immediately.
  • FindObjectOfType could still find the “destroyed” game object.
  • --------------This is info on Singletons & more from Nina
  • Implementing the Singleton Pattern in C#
    ---------When I go to the main menu the score text disappears even though it’s part of dontDestroyOnLoad.
    Does it get destroyed or does it just contain an empty string? It is still possible to destroy “DontDestroyOnLoad” objects
    with the Destroy method.
    Do you understand the concept of a singleton? If so, and if you feel that Rick’s singleton implementation causes
    unsolvable problems with your own ideas, you could try to replace it with another singleton version (first version, remove the sealed keyword, replace Singleton with your classname). You are not obliged to keep his code. His code solves his problems, not necessarily yours.
    --------I think I’m onto something.
    Yes, the two methods are connected. In the LoadGame method, you could try to swap the two method calls to ensure
    that ResetGame gets executed. Maybe LoadScene terminates the LoadGame method early and prevents ResetGame from being
    called in your case.
    /*Look up the sceneChanged delegate in the API and read the example. Then apply the example to your own project.
  • You know if-statements, so you just have to figure out which scene was loaded.
  • Check the SceneManager class in the API. You’ll find something that will solve this problem for you.
  • What I understood is that you want to destroy something in a specific scene.
  • This means that you need to check something when a scene got loaded.
  • And that something is: Which scene got loaded? Before you implement any complex logic,
  • you just log the name of the current scene into your console after that scene got loaded.
  • And when you load another scene, you do the same again. And where do you do that?
  • In a script which is attached to one of your persistent game objects (that are supposed to get destroyed in a certain scene).

Step by step. Just keep it simple. Use the example from the API. If in doubt, copy and paste it as it is.
Then log the name of the current scene into your console.
And then share either the result or what you managed to do before you got stuck.

Once this works, the rest is not that difficult anymore.

Below is what I’m trying to do. Above is Nina’s replies, the script is the one on the link.
“don’tDestroyOnLoad” to keep the score & other elements transferring from scene to scene.
Is there a way to destroy that on a certain scene?
What I mean is I need dontDestroy to work while I’m on stages 1-4.
But on the congratulations, main menu & game over stages I’d like to destroy these gameObjects that are no longer necessary.

I tried a basic destroy code that didn’t work here is an example

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

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

private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
    // here you can use scene.buildIndex or scene.name to check which scene was loaded
    if (scene.name == "MainMenu")
    {
        // Destroy the gameobject this script is attached to
        Destroy(gameObject);
    }
------- & even more basic

void Start()
{
Destroy(GameObject.Find(“object to be destroyed”));

}

If you are wishing to destroy an object you have already established as a singleton with a don’t destroy on load ability,
you might need to re-think how you are setting up that object. The whole point of Don’t Destroy is so you won’t destroy the object.
If you are wishing to destroy that object only on certain scenes, but use it on other scenes,
then may I suggest a looking into making it a child of a singleton and using .setActive(true/false)

*/
,…

umm…

Sure. Destroy(TheParentGameObjectYouWantToDestroyThatHasDontDestroyOnLoad);

It really isn’t anymore complex than that. The problem is the logic to how best to achieve this and where you do it. You may want to do it in say, the main menu scene. Have an GameObject that only exists in that, that goes

var killThis = FindObjectOfType<TypeYouWantDestroyed>();
if (killThis != null) Destroy(killThis);

But none of this is really that complex. If you’re up to tilevania, you’ve learned enough to be able to do it already you just had to combine a couple things you’ve learned and do a little bit of reading. It just takes a bit of sitting back and looking at the problem… that is… once you know how to do a fair few things, you learn different ways to accomplish different tasks. I think you’re getting to the point where you can’t see the forest for the trees.

When I said go down the rabbit hole, I mean, go wider, not deeper down the same rabbit hole, time and time again. You need to learn when to discard information that doesn’t suit your needs. You don’t need to go into UnityActions to solve something like this.

At a guess, you’re trying to add on extra abilities on to simple programs and hitting the wall hard. I think you need to go wider in your learning first otherwise you’re going to frustrate yourself to no end. There are some bits you still need to learn and experience more simple ways to accomplish tasks. Learn more topics, but not go as deep as this until more pennies drop into place. Since you’re struggling on stuff like that, I still suggest that you go through more tutorials and come back to tackle the task when you’re a little more seasoned.

You’ve got a lot of passion. I wish I had as much passion for the topic as you.

I tried a basic destroy code that didn’t work here is an example

What does “not working” mean? Your code looks fine to me.

When talking about problems, always explain what you expected to happen and what happened instead because “not working” can mean everything from “I expected X to happen when I press the Play button but X did not happened” to “my computer exploded after I executed this code”.

If this was my code, I would check if the OnSceneLoaded method gets called when a new scene gets loaded. I do that with a simple Debug.Log. And while we are on it, we could also check the name of the scene that has been loaded.

private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
    Debug.Log("Scene loaded: " + scene.name);

    // rest of your code
}

Notice that I put the Debug.Log outside the if-block. This is important because there is a chance that your code “is working” but the if-block does not get executed for some reason. The condition might either be wrong or you are getting an unexpected value during runtime. Instead of wasting your time with guessing around, you simply add a Debug.Log to check that.

The next step is to interpret the information in the console. Maybe the console says “Scene loaded: Main Menu”. In that case, it is clear that the condition is wrong because your scene is named “Main Menu” instead of “MainMenu”.

Or you are getting a completely different scene name, maybe “SampleScene”. And then you notice: Oops, I never gave my “Main Menu” scene a proper name.

And if the OnSceneLoaded method did not log any message into your console, you could add a Debug.Log to the Start method. Or simply comment out the entire Start method to see what happens.

Long story short, you seem to be on the right track. All you have to do now is to debug the code a bit to see where the problem might be. If you understand the problem, you will very likely be able to solve it.

Last but not least, since my previous answers might have been a bit confusing: I do not know much about your project or the problems you’d like to solve. And my way of thinking is very likely different from yours, which is completely fine. For these reasons, there is always a chance that I’m misunderstanding your problem(s), and there is also a chance that I’m writing nonsense (I try to avoid that but I’m not perfect). When reading answers or “solutions”, always filter the information and use what you feel might help you with your problem. Never assume that every single detail in somebody’s answer is relevant for you.

Thank you Nina. I appreciate what you’re doing. As far as I can tell you know what I want to do. I just don’t understand your possible resolution. I know in unit there’s usually at least 5 different ways of doing the same thing & that anything we can think of can be done.
Anyway this is where I’m at:
------When I use the go to “Main Menu” command I want any gameObject with the Levels.cs, GameSessions.cs, or BlockSessions.cs (which has the reset game & kill me command linked together) to reset game, deleting everything but the audio player singleton I’m using for my soundtrack. My levels script is on my buttons. On some stages I put 1 of those 3 scripts on the game session game object & I have it’s children be the canvas & player. This is so when I click on the “Main Menu” it will destroy everything in my canvas, & my player. This also is so when I’m going from stage to stage the score(which is part of the canvas) & player will (IDK the term) continue on. This is dontDestroyOnLoad.
What happens is sometimes when I hit the main menu button (with the Levels.cs component):
1- Everything I want to kill itself commits suicide & I’m on the main menu. This is the goal.
2- For whatever reason my canvas disappears from the scene. I have no idea why.
3-Nothing at all. I go to the Main Menu & still have my score & lives (but not the player) are still there, never dying.
I have not figured out why I get different results from (what appears) to be the same process.
I realize if I kill the parent the whole family dies so that’s my goal to over kill the daddy thus why I have reset & plural destroy commands.
Thank you for helping me learn.

By my reading of this code you sent me if I add this to my “Main Menu” command it will destroy anything I tell it to.
I can’t take a break for longer then a few hours a night. Thanks for recognizing the passion is real.
You really have no idea brother. This idea is really amazing wait until I upload the web-thingy version.

I solved multiple problems in my code. Maybe only a part of my code is relevant for you. Or nothing is relevant for you. Ignore it for now and focus on what you already have.

When I use the go to “Main Menu” command I want any gameObject with the Levels.cs, GameSessions.cs, or BlockSessions.cs (which has the reset game & kill me command linked together) to reset game, deleting everything but the audio player singleton I’m using for my soundtrack.

Try to simplify the problem. Instead of “destroy A, B C, F, J, X, Y and some other things” and “but don’t destroy my audio player”, you could parent “A, B C, F, J, X, Y and some other things” to a root game object, and you destroy that root game object. As you already figured out, the entire family gets destroyed if you destroy the parent.

And the audio player could be a on a separate game object. This way, you would not have to implement any complex logic distinguishing between “A, B C, F, J, X, Y and some other things” and your audio player.

If you need to distinguish between objects, you need if-statements and comparisons.

For whatever reason my canvas disappears from the scene. I have no idea why.

Is it attached to a game object that gets destroyed or is it a child of a game object that gets destroyed? Also check if you accidentally attached the wrong script to your game object.

Privacy & Terms