- Home /
The question is answered, right answer was accepted
Don't understand how to use DontDestroyOnLoad.
So I've been trying to understand how to get DontDestroyOnLoad to work for a while now and I'm still confused. I do understand that you can use it to make data persist through the transition of scene changes which is exactly what I'm trying to do. I just want to make the players score to continue to the next scene with the score they ended the first scene with. I've also tried messing around with PlayerPrefs but I found out that that's not really what I should be using for this kind of thing. Here is my code for the score:
using UnityEngine;
using System.Collections;
public class ScoreManager : MonoBehaviour
{
public GUIText scoreText;
public static ScoreManager Instance;
private int score;
void Awake()
{
if (Instance == null) {
DontDestroyOnLoad (gameObject);
Instance = this;
} else if (Instance != this)
{
Destroy (gameObject);
}
}
// Use this for initialization
void Start ()
{
score = 0;
ScoreUpdate ();
}
public void PlayerSave()
{
ScoreManager.Instance.score = score;
}
public void AddScore(int newScoreValue)
{
score += newScoreValue;
ScoreUpdate ();
}
// Update is called once per frame
void ScoreUpdate ()
{
scoreText.text = "Score: " + score;
}
}
I thought this would work, and I know how the singleton pattern works (at least I think.) but what happens when I play the game is after the first point I can't gain anymore points, and then going to the second scene the score restarts back to 0 and once I collect the first point the game stops working. If someone could please help me with this I would greatly appreciate it! And if anyone could help explain these processes to me or show me where to look for a good explanation that would be very helpful, Thank you!
Also here is my ScoreManager script. Just in case this could be useful.
This might be a part of the issue, where is the void AddScore() being called and passed the parameter?
Change your code in Awake() to following :
if (Instance != null && Instance != this) {
Destroy (gameObject);
return;
}
Instance = this;
DontDestroyOnLoad (gameObject);
This does exactly the same but is not necessarily more readable. The original code is easier to read as it has one condition per if statement and each statement handles a seperate case.
Answer by Bunny83 · Sep 09, 2016 at 06:49 AM
There are a lot things unclear about your setup. First of all what's the point of "PlayerSave"? If "ScoreManager" is a singleton there should only be a single instance of this class at any time. So "copying" the score of the "current" ScoreManager to the one stored in the instance variable makes no sense.
Next thing is: DontDestroyOnLoad only works on root gameobjects. So if you use it on a nested gameobject it has no effect at all. When the parent is destroyed all childs will be destroyed as well.
Another possible problem is your reference to the "GUIText". If this GUIText is not part of the singleton instance (so it doesn't persist) you will end up with a missing reference exception.
A minor thing you should fix: Remove the comment on UpdateScore. Far worse than an uncommented code is wrongly commented code. Comments should clarify things when something is difficult to understand. Good code doesn't need any comments because it's clear what it does. When something isn't clear you can add a comment to tell others (or yourself) why you did this or that. A wrong comment does the exact opposite. It confuses / misleads the reader. So code that is actually clear to understand gets harder to understand or is even misinterpreted.
Thank you so much for answering first of all and sorry for the late reply, but I looked at it and it looks like you're right in your second point, where the "GUIText" isn't part of the singleton instance. So I checked what happens to the score manager in the scene and it stays there but the GUIText is deleted. How would I make it apart of the singleton instance? Also thanks again for the help!
I feel very silly right now but I have the GUIText in the singleton instance now and everything works!! Thank you so much!!!
Answer by D3mon1zA · Sep 09, 2016 at 05:44 AM
You have :
{
if (Instance == null) {
DontDestroyOnLoad (gameObject);
Instance = this;
} else if (Instance != this)
{
Destroy (gameObject);
}
it should be (I think) this:
{
if (Instance == null) {
DontDestroyOnLoad (gameObject);
Instance = this;
} else if (Instance != null)
{
Destroy (gameObject);
}
sou your else if should be asking if it is not equal to null instead of not equal to this. I think the reason for this is if 2 instances do occur they will delete each other? I'm not entirely sure on if that is correct or not (I have only just learn't this myself) but give it a shot see how you get on also try adding:
using.System;
using.System.IO
this video Might help https://www.youtube.com/watch?v=yxziv4ISfys
Sorry but that makes no sense.
Awake is only called once per object. So the first instance that executes this code will see that there is no instance yet and makes itself "the" instance. The second (or third, or any other) instance will see that there is already an instance. If that one instance isn't themselfs they destroy themselfs.
Your condition ( Instance != null
) would allow that the actual singleton can destroy itself if somehow the code is executed twice.
Also importing System
or System.IO
is completely nonsense. You would only import those namespaces when you need any class from those namespaces. Also in Unity it's generally better to avoid importing System
as it has some collisions with the UnityEngine namespace. Apart from that even $$anonymous$$icrosoft suggests to simply use the full qualified classname when you only need it one or two times. importing a namespace only makes sense when you need multiple things from a namespace.