Duplicate GUIDs with DontDestroyOnLoad in Unity

I’m encountering issues with duplicate GUIDs when using DontDestroyOnLoad with objects that have SceneObjectGuid components. Here’s my setup:

The Issue

  • I have a DontDestroyOnLoad script that manages persistent objects across scenes
  • Some of these objects have SceneObjectGuid components (from Unity.Tutorials.Core)
  • When loading new scenes, I get errors about duplicate GUIDs

The specific error is: ArgumentException: An item with the same key has already been added. Key: bfc1c1e5-b8c8-40e0-b058-a2c26748921a

Current Implementation:

Here’s my DontDestroyOnLoad script: using UnityEngine;using Unity.Tutorials.Core;public class DontDestroyOnLoa - Pastebin.com

Basically, I am working with the Unity VR multiplayer template, and I have scenes that go from 0 to a different scene back to 0 and disconnect the clients, not the host. scene 0 has a bunch of objects like the Network Manager VR Multiplayer and XRI connection Manger (these 2 are the ones with the guide issue) and others that need to persist across scenes but never duplicate when they are at scene 0 hence the script attached.

Does this script require you to place it in scene? If so then it is defective.

Try this approach instead:

Simple Unity3D Singleton (no predefined data):

Unity3D Singleton with a Prefab (or a ScriptableObject) used for predefined data:

These are pure-code solutions, DO NOT put anything into any scene, just access it via .Instance

Alternately you could start one up with a [RuntimeInitializeOnLoad] attribute.

There is never a reason to drag a GameObject into a scene if it will be DontDestroyOnLoad.

If you do:

  • you may drag it into something else that isn’t DDOL. FAIL
  • you may drag something else into it that isn’t DDOL. FAIL

Just DO NOT drag anything into a scene that will be marked DontDestroyOnLoad. Just Don’t Do It!

I replicate the important part here and want to note that this is awfully overcomplicated (also unclear who or what sets foundOriginal before that script’s Awake runs):

void Awake()
    {
        // Check for existing instances
        if (!foundOriginal)
        {
            isOriginal = true;
            DontDestroyOnLoad(gameObject);
 
            foreach (GameObject obj in managedObjects)
            {
                if (obj != null)
                {
                    // Remove SceneObjectGuid components
                    SceneObjectGuid[] guids = obj.GetComponentsInChildren<SceneObjectGuid>(true);
                    foreach (SceneObjectGuid guid in guids)
                    {
                        DestroyImmediate(guid);
                    }
 
                    DontDestroyOnLoad(obj);
                }
            }
        }
    }

Instead, all you really need is this:

void Awake()
{
    DontDestroyOnLoad(gameObject);
    Destroy(this);
}

Then simply add that script to each object that you want to be in DDOL. This provides the most flexibility AND most importantly, it’s calling out to you from the Inspector “hey look at me, I’m going to be in DDOL no question about it!”. :wink:

The removal of the guid scripts should be a separate MonoBehaviour too, and you also put that on every game object that needs to do this.

Prefer to make more but simpler components. That way you can make a lot of reusable building blocks rather than highly specialized code that’s also going to become more and more confusing.