Problems with transporting Array to next scene, using DontDestroyOnLoad

Hey there,

i got a problem with transporting an array to a new scene with loadlevel. Here is what i’ve got:

My Class I use as Array later:

public class PlayerInfos : MonoBehaviour {

	[HideInInspector] public NetworkPlayer pNetworkId;
	[HideInInspector] public string pName;
	[HideInInspector] public string pTeam;
	[HideInInspector] public int pGold;
	[HideInInspector] public int pIncome;
......

Here I define the array:

public class DedicatedServer : MonoBehaviour {

	[HideInInspector] public PlayerInfos[] playerinfo;

	void Start () 
	{
		objGameStatus = GetComponent<GameStatusControll>();

		playerinfo = new PlayerInfos[7];
		for(int i = 0; i <= 6; i++)
		{
			playerinfo[i] = new PlayerInfos();
		}
	}

So everything works fine, until I load the level and use any function that used the array, for example:

public int GivePlayerId(NetworkPlayer info)
	{
		for(int i = 1; i <= 6; i++)
		{
			if(playerinfo[i].pNetworkId == info)
			{
				return i;
			}
		}
		return 0; // if 0 is returned, other functions know that there is no id
	}

The error message I receive is:

Here is the part where I load the next scene:

DontDestroyOnLoad(transform.gameObject);
Application.LoadLevel("Scene-01");

The Object is a null object with DedicatedServer Script attached. The function GivePlayerId is part of DedicatedServer.

I hoped I could transport the array as part of the GameObject to the next scene, but somehow it does not seem to work. Anyone of u has some ideas?

In DedicatedServer.Start: You should never be newing up a MonoBehaviour instance yourself - do this instead:

public class DedicatedServer : MonoBehaviour
{   
    [HideInInspector] public PlayerInfos[] playerinfo;
     
    void Start ()
    {
        objGameStatus = GetComponent<GameStatusControll>();
    
        playerinfo = new PlayerInfos[7];
        for(int i = 0; i <= 6; i++)
        {
            playerinfo[i] = gameObject.AddComponent<PlayerInfos>();
        }
    }
}

If this is the same object that you are marking with DontDestroyOnLoad, then it should survive the level load with all components intact, including your now attached PlayerInfos.

Thanks, that realy solved my problem. But isn’t it possible to transport the array without “attaching” the script multiple times (length of array) to the object?

If your script is a MonoBehaviour derived object then no, it should only ever exist as a component attached to a GameObject.
However, it looks to me like your PlayerInfos object should really be derived from ScriptableObject, in which case your code would change to this:

public class PlayerInfos : ScriptableObject
{
    ...
}

public class DedicatedServer : MonoBehaviour
{
    [HideInInspector]
    public PlayerInfos[] playerinfo;

    void Start()
    {
        objGameStatus = GetComponent<GameStatusControll>();

        playerinfo = new PlayerInfos[7];
        for(int i = 0; i <= 6; i++)
        {
            playerinfo[i] = ScriptableObject.CreateInstance<PlayerInfos>();
        }
    }
}

And again u solved it :stuck_out_tongue: many thanks to you.

So is it that because it isn’t meant to be attached to an object this way, it wont be destroyed when loading a new scene? Just for my understanding

Not exactly - yes, a ScriptableObject isn’t meant to be “attached” to an object the same way a MonoBehaviour is, but it’ll normally still be destroyed when loading a new scene. The reason they aren’t in your case is because your ScriptableObjects are being referenced by an object that is itself explicitly marked by the DontDestroyOnLoad method - so its your marked GameObject that is preserving the ScriptableObjects by holding references to them.

Technically, the DontDestroyOnLoad method accepts an Object parameter, which means you can pass in GameObjects and ScriptableObjects, but in testing it behaves unpredictably: ScriptableObjects marked to not be destroyed will be destroyed anyways if nothing referencing them survives the scene load; except if you’re running from the editor and inspect an object referencing it first, mark the ScriptableObject to not be destroyed (but not the object referencing it) and change scenes. You’ll end up with a ScriptableObject floating around with nothing referencing it. Super weird, huh?

Haha yes, soungs weird. But thank you so much for taking the time and explaining this to me. That really helped me!

So this problem is solved!

My pleasure sir, good coding to you!