Prevent gameobject from being spawned more than once.

I want to transfer information between scenes and I use the “DontDestroyOnLoad()” function that prevents the game object from being destroyed once you load a new scene. Then I can find a certain script in the new scene and set the values I want to transfer. However once I load the new scene then go back to the original scene the same game object spawns again, there are two of the exact same game object. I want to only have ONE! I have tried something like this…

void Awake() {
	DontDestroyOnLoad(this);
	
	if(PlayerPrefs.GetString("alreadySpawnedGameObject", "false")) {
	
		Destroy(gameObject);
	
	}
	else {
		PlayerPrefs.SetString("alreadySpawnedGameObject", "true");
		
	}
	   
}

… the only problem is that player prefs don’t use booleans and they don’t return a boolean value. How do I check if the gameobject has already been spawned then if it is, it will destroy itself ?

To compare strings you use the boolean operators != (not equal to) or == (equal to) like this:

if(PlayerPrefs.GetString("alreadySpawnedGameObject") == "true") {
    Destroy(gameObject);
}

I think the way you’re doing things can easily lead to messy situations. I’m guessing the problem that you’re facing after making the first change is the player no longer spawns (or to be precise, it destroy itself after it spawned) since the value wasn’t being reset to false. And after making the second changes (I may be wrong on this but from my understanding…), I think it would lead to another character being spawn the 2nd time you go back to the original scene. Since the value would go:

  1. 1st time enter the original scene:
    Spawn the player and set the value
    to true
  2. 2nd time enter the original
    scene: Spawn and destroy the newly
    spawned character and set the value
    to false
  3. 3rd time enter the original
    scene: Spawn another character that
    doesn’t get destroy since the value
    is now false and set the value to
    true

I think wouldn’t it be easier to have a static value inside the script? You can create a static bool and use that on whether you should destroy (or spawn if you’re spawning through script) the character. Most of the code will remain the same, for example:

static bool spawned = false;
	void Awake(){
		DontDestroyOnLoad (this);

		if(spawned) {			
			Destroy(gameObject);
			
		}
		else {			
			spawned = true;			
		}
	}

You can change the name of the object that is created for the first time when it change level, so next time you load the level you can delete the new one.

This code assume that the level that is load after the you that contains your object is 1 (you can find livel number in buil settings) and that your object name is: Your_Object

void Update()
{
      //when application load level 1 is adds "- old" to the name of your object
       if(Application.loadedLevel == 1)
          this.gameObject.name += " - old";

}

and then add a start function like this:

void Start()
{
  //if it find the old object it thelets the new one create
  if(GameObject.Find("Your_Object - old"))
    Destroy(this.gameObject);
}

My advice is — don’t use DontDestroyOnLoad at all. It’s a dodgy, unintuitive and ugly method. Also it doesn’t do what it’s called. It actually recreates the object as far as I’m concerned.

I’d advice to have a scene workflow independent storage of dynamic gameplay data. By that I mean the data that’s altered by the player. This data is changed through playing the game and depending on this data you dynamically instantiate objects when entering a new scene. PlayerPrefs is not the worst candidate for this storage role.

In case of your player, you simply have a conventional bootstrapper game object in each scene with a player prefab injected into it. The bootstrapper then creates an instance of the player from the prefab. Bam! No duplications, no inconsistencies.

This approach is of course not as quick-hacky, as you can’t just declare a variable in the player and expect it to persist between the scenes. You now have to make sure you save the state for further scenes. But in bigger games a separate persistence layer is almost inevitable anyway, so why not now.

Satisfying read on the topic:

http://t-machine.org/index.php/2015/03/15/some-thoughts-on-loading-scenes-in-unity3d/

Can you just store the persistent info in static variables? These could be globally accessible and stored within a single class avoiding this issue altogether. If your data does not need to be in a monobehaviour you shouldn’t put it in one.

public class GameSettings
{
  public static int score = 0;
  public static int lives = 3;
  public static string playerName = "Bubba";
}

public class LevelUI : MonoBehaviour
{
  public Text score;
  public Text lives;

  void Awake()
  {
    score.text = GameSettings.score;
    lives.text = GameSettings.lives;
  }
}

Something like that.