Problem moving my player between levels?

Hi all, I have an issue I can’t quite figure out the right way to handle it.

I have my player fully initialized, carrying armor, weapons, etc…

Therefore, instead of recreating the player every time it moves from level to level I wanted to use “DontDestroyOnLoad”

Then when I switch levels, the first thing I do is look for the spawn point and update the players position to that point.

The level is loading, but if I don’t use a CoRoutine, when I perform a find I’m finding object from the first level, and none from the new level. If I use a coroutine and yield after the loadlevel, but before the find, then it never returns from the yield. I’m assuming because the object was deleted, but I placed a "Don’tDestroyOnLoad on one of the component classes of the player.

I’m assuming maybe only the component class is persisted between levels and not the player and all of its sub-components or I have another issue?

Is this the right idea, or should I be thinking about it differently?

I suspect the player is getting deleted too because I’m losing the camera. If I want everything to persist where do I put DontDestroyOnLoad?

	public IEnumerator CoLoadLevel (GameObject player, string level, int levelPrefix, string spawnpoint) 
	{
		Debug.Log("Jumping...");

		// There is no reason to send any more data over the network on the default channel,
		// because we are about to load the level, because all those objects will get deleted anyway
		Network.SetSendingEnabled(0, false);
		// We need to stop receiving because first the level must be loaded.
		// Once the level is loaded, RPC's and other state update attached to objects in the level are allowed to fire
		Network.isMessageQueueRunning = false;

		// All network views loaded from a level will get a prefix into their NetworkViewID.
		// This will prevent old updates from clients leaking into a newly created scene.
		Network.SetLevelPrefix(levelPrefix);
		Application.LoadLevel(level);

		yield return 0; //new WaitForSeconds (1);
		yield return 0; //new WaitForSeconds (1);

		// Allow receiving data again
		Network.isMessageQueueRunning = true;
		// Now the level has been loaded and we can start sending out data
		Network.SetSendingEnabled(0, true);
		// Notify our objects that the level and the network is ready
		Debug.Log("Seding On Network Load Level");

                // Find the SPAWN location in the new level and update the players position to this new location
		//GameObject _spawn = (GameObject)GameObject.Find(spawnpoint);
		foreach ( GameObject _portal in GameObject.FindGameObjectsWithTag("Portal"))
		{
			if ( _portal.name == spawnpoint )
			{
				// Set the player's current position equal to the position of the jump gate
				player.transform.position = _portal.transform.position; 
				break;
			}
		}
		
		Debug.Log("Send " + count.ToString() + " OnNetworkLoadLevel messages");
	}

Since your avatar is Yoda, I’m going to caveat my response by waving my hand and saying, “This is not the answer you are looking for.”

IMHO…

Don’t use a coroutine.

In your active level, call your networking script to turn off the networking, load the next level, and in the level that loads, call your networking script to turn networking back on, and then do your search for the spawn point.

DontDestroyOnLoad can be used at anytime. If you create an empty at the start of your game, call DontDestroyOnLoad on it, and then attach the player (and whatever else to it), and you should be fine.

As a side note, I would have thrown all the networking code into one script with separate functions instead of having it in the routine above. It keeps everything in one place instead of having it scattered throughout multiple scripts. It just makes it easier to maintain, change and troubleshoot.

Hope this helps.

Lockbox,

First thanks for the reply I appreciate the effort.

Lets not worry about the networking code. Its really not relevant to my issue.

I’ve already tried running the loadlevel without a coroutine. When I do I reach the FindGameObjectsWithTag but it returns objects in the previous level, not the new level I just loaded. I also tried running the FindGameObjectsWithTag in the parent function after returning from the loadlevel, but it still produces the same result. That’s why I was trying the CoRoutine with a yield, but now I never reach the FindGameObjectsWithTag. I think it’s because the object isn’t staying loaded even though I’m using DontDestroyOnLoad. I suspect I’m doing something wrong with where I have DontDestroyOnLoad being executed. My player is a prefab that is instantiated when I load the first game level. Attached to my prefab is a component class and in the awake method I call the DontDestroyOnLoad. In a second component class also attached to the player prefab. In that second class is where I’m running the loadlevel code. I assumed that the DontDestroyOnLoad would keep the entire object loaded but now I’m wondering if it doesn’t work the way I thought it did?

Any other insights would be appreciated.

Thanks all.

So what you’re saying is, without a coroutine, when the next level loads, you see the previous level’s objects in the hierarchy. Is that correct? If this is the case, I would venture to guess that there is a problem with the code beyond what you’ve explained and the code above, that has nothing to do with your DontDestroyOnLoad issue.

It’s some sort of timing issue. The new level is loading, but not immediately after calling Application.LoadLevel. If I don’t use the debugger I’ll see the new level load. If I enable a temp camera (not the player camera) as part of the level, I’ll properly see the level. However, I’m turning off the temp camera as my player already has a camera. Unfortunately the player doesn’t seem to be sticking, because the camera is gone and all I see is gray, so I’m pretty sure it’s the DontDestroyOnLoad that is the issue, but I’m trying to understand where I’m going wrong with it. Unless someone else has some ideas, I guess I’ll just keep messing with it. I suspect I’m close and probably doing something really dumb, as its usually the case :slight_smile:

Add permanent cameras in both levels and disable the the player’s cameras…

I think I resolved my issue. I set a breakpoint on the DontDestroyOnLoad, and I was never reaching it. I had it as the first line of code in my awake function. Apparently it doesn’t work quite as I expected. I moved it to the start function, and now it seems to be working right. I have other issues to work through, but I think I’m over this hurdle. I really should have caught this on my own much earlier on, but I just made the assumption that everything in the awake function was running. Apparently I need to go back and reread how awake works, but I’ll deal with that another time.

Thanks for the suggestions, I appreciate the help.