What about loops instead of statics?

What I used to do is something like this, I know it is the same as using the private static state, actually worse because it is even slower, but I just don’t like statics at all, I got traumatized thanks to old Unity official tutorials :joy:

        // PRIVATE STATE
    bool hasSpawned = false;
    public bool GetHasSpawned { get => hasSpawned; }

    // PRIVATE
    private void Awake()
    {
        foreach (PersistentObjectSpawner pOS in FindObjectsOfType<PersistentObjectSpawner>())
        {
            if (pOS.GetHasSpawned && pOS != this)
            {
                Destroy(gameObject);
                return;
            }
        }

        SpawnPersistentObjects();

        hasSpawned = true;

        DontDestroyOnLoad(gameObject);
    }

I’ve also seen some crazy “singletons” using ScriptableObjects.

I’m not entirely sure this would avoid spawning more objects in a scene change…

1 Like

You are totally right, it didn’t work at all. I edited the code and now it works.

I don’t like that approach, it leaves a useless game object lying around the scene. So maybe there’s a better way, like checking if any of the spawned objects are already in the scene, something like this perhaps:

    private void Awake()
    {
        GameObject objectToLookFor = GameObject.Find(persistentObjectPrefab.name + "(Clone)");
        Debug.Log(persistentObjectPrefab.name);

        if (objectToLookFor == null)
        {
            SpawnPersistentObjects();
        }

        Destroy(gameObject);
    }

This works too but I’m not sure, maybe the private state is enough.

This approach will work, but from a pure performance standpoint, it’s probably the worst possible solution, because of the way Find works… it will crawl through the entire primary scene before finally crawling through the DontDestroyOnLoad scene. (This is actually also a problem with implementations of the Singleton pattern that look for other copies of the script instead of using an Instance variable, it’s “cleaner” but slower than molasses).

Unfortunately, there’s not really a perfect Singleton solution. Our “Better than a Singleton” solution is, in and of itself, just another Singleton (but personally, it’s my favorite solution). Sometimes, you just need a Singleton.

1 Like

Yeah, that method is way too slow, not suitable for games that change scenes constantly.

I’m playing a little with this concept and see what if I manage to create something, not necessarily better, I don’t think I can do that with my current knowledge, just something to have a little fun with.

This is how one learns best. :slight_smile:

1 Like

Hopefully necro of a thread isn’t too bad on the forums?

I was looking into more of this as well today, just trying out new things, seeing what possibilities were available. I ended up experimenting with PlayerPrefs.

I believe it’s harmless since it only cares about whether an object has been spawned or not and shouldn’t be game breaking.

using UnityEngine;

// Placed on the GameObject that 'PersistentObjectSpawner' instantiates. (Core GameObject)
public class PlayerPrefKey : MonoBehaviour
{
    GameObject instance = null;

    void Awake()
    {
        if (instance == null)
        {
            instance = this.gameObject;
            PlayerPrefs.SetString("OBJECTSPAWNER_KEY", "OBJECTSPAWNER_KEY");
        }
    }

    void OnDestroy()
    {
        PlayerPrefs.DeleteKey("OBJECTSPAWNER_KEY");
    }
}

I place the PlayerPrefKey on the Instantiated GameObject as a Component. This GameObject prevents duplication from LoadScene just like the RPG course had set up.

And when it’s OnDestroy is called, it simply removes our stored key and allows the PersistentObjectSpawner to instantiate a brand new one on the next awake.

using UnityEngine;

public class PersistentObjectSpawner : MonoBehaviour
{
    [SerializeField] GameObject persistentObjectSpawner;

    // PRIVATE

    void Awake()
    {
        bool hasSpawned = PlayerPrefs.HasKey("OBJECTSPAWNER_KEY");
        if (hasSpawned) return;

        SpawnPersistentObject();
    }

    void SpawnPersistentObject()
    {
        persistentObjectSpawner = Instantiate(persistentObjectSpawner);
        DontDestroyOnLoad(persistentObjectSpawner);
    }
}

Let me know any pitfalls this could cause… thanks.

Privacy & Terms