Scene management with PUN (Photon Networking) [solved]

Hello,

I am making a 4 person coop game. I am finishing up my first level and want to have all 4 players advance to the next level together, keeping all of their position and data, hopefully with a minimal or fast transition.

I am a little new to multiplayer programming but have learned a fair amount. There is a delay at the beginning of the game when players join and their models get instantiated. I am hoping to not go through that at every scene load. My game is an outdoor game with different terrains, although I am not making a massive singular world. I need to load new terrains, with different objects, rocks, etc.

Any help is appreciated!

first, iā€™m new too, I just started learning photon

What I do is:

Set PhotonNetwork.AutosyncScene = true; at the start

then

If (PhotonNetwork.IsMasterClient)
{
PhotonNetwork.LoadScene(ā€œSceneNameā€);
}

this way all clients will load the same scene that the host loadsā€¦

3 Likes

Awesome - thank you that is very helpful!

So a couple of typos in there - got those ironed out and it is still not working as I would hope. I added:

PhotonNetwork.automaticallySyncScene = true;

Into the start statement in my connect and join script.

and :

if(Input.GetKeyDown("p")) {
     if (PhotonNetwork.isMasterClient) {
          PhotonNetwork.LoadLevel("level2");
      }
}

into my player control script.

(There is a Network control object in my scene that connects to the network and instantiates players at predefined spawn points.)

The behavior I am seeing is that the scene does load for the Master Client, but nothing happens for the other client?

Could the new scene assets maybe be loaded as an asset bundle locally or from the web? My thinking is that this strategy would eliminate the delays related to joining the network, etc.

Thx!

Doing a little more digging. I am trying to do this with an executable and in the editor - been working that way to test two players. Thought that might be getting in the way?

So I switched it around, started the executable first then loaded the scene in the editor. (this case the editor is the MasterClient. When I hit the p, to load scene it does the same thing.

But it is throwing this error -

CreateRoom failed. Client is not on Master Server or not yet ready to call operations. Wait for callback: OnJoinedLobby or OnConnectedToMaster.
UnityEngine.Debug:LogError(Object)

So are you waiting for either of those callbacks before you try to create the room?

I have an OnJoinedLobby callback, but it only triggers on the first time I run the level, but not when the PhotonNetwork.LoadLevel(1) is called by the master client.

The level is now loading for both MasterClient and Client.

The way I set up the first level was to show a screen which allows a player to choose a room (right now focusing on private rooms only) - when the other player types in the same room name - both players can play the level together.

So what is happening now,

  1. Both players successfully join the game, (the OnJoinedLobby fires checked with Debug Script)
  2. The master client calls PhotonNetwork.LoadLevel(1) both MasterClient and Client load the level
  3. The join room UI where they can type in the name of a room again shows, same for the client.
  4. The OnJoinedLobby never fires after loading a new level. If the MasterClient types in the same room name as before, it throws the wait to join lobby error. It shows the scene, but both players are gone.

I would ultimately have a loader scene where room names are created or joined.

The way this is set up, on initial load, if any player types in the room name, it gets the roomlist, if the room does not exist, it creates it, otherwise, it joins it - so it seems that it would stand to follow that when the Master Client types in the same room name after triggering the level load, it would ā€˜reā€™ join it. I feel like I am missing something basic here.

  1. Any advice as to why this is not working?
  2. Do players need to rejoin the network when changing levels?
  3. Any thoughts on loading level items as custom packages instead of loading a new level? I want the players to be in the same physical position and have the same health, items etc. so this seems like a direction that might be good to explore?

A little more info.

[edit]

I added:

void awake() {
    DontDestroyOnLoad(this.gameObject);
}

in the player control scripts, but they are still getting destroyed when the scene loads?

The problem appears to have been with the OnDestroyUnload and not Photon.

This post suggests putting the DontDestroyOnLoad in the start and awake, which worked for me, not 100% why. Marking as solved.

RE: my item 3 above - The scene load happens much faster than expected, so no need for this.

1 Like

It is a very simple explaniation, it just means that you were not connected to the Photon Server, like you probally called photon functions before you actually connected to the photon servers, making that error

Hi, guys. I have a problem. My game was published on itch.io, its an online game and I have a normal mode and I also started to create a new mode, how can I join both of them? Like, in the main lobby there are 2 buttons: play(normal mode) and play(new mode), first should open a one scene, second should open other scene, but when I opened the second one, I joined scene from the first button. How can I change it?

Title: Issue with Photon Object Spawning Over Network in a New Scene

Description: I am facing a problem with spawning new Photon objects over the network after loading players into a new scene using Photon PUN. The issue occurs when the master client hits the ā€œStart Gameā€ button in the game scene, which then loads both players into the new scene. The spawning system works flawlessly in the menu scene, but once players transition to the game scene, the PhotonNetwork.Instantiate function only spawns objects for the local player who initiated the spawn, and remote players canā€™t see the newly spawned objects. The relevant script sections are from the Launcher scriptā€™s StartGame function, which calls the LoadPlayer function, and the PlayerSpawner scriptā€™s SpawnPlayer function. We have tried ensuring PhotonNetwork.AutomaticallySyncScene is set to true, and the OnJoinedRoom callback correctly calls SpawnPlayer, but still encounter the issue. Additionally, PlayerSpawner is already implemented as a singleton to avoid any potential conflicts. Any insights or suggestions would be greatly appreciated in resolving this object spawning problem over the network in a new scene. Thank you!

Snippet from Launcher script (StartGame function):

public void StartGame()
{
LoadPlayer();
if (PhotonNetwork.IsMasterClient)
{
PhotonNetwork.LoadLevel(1);
}
}

Snippet from PlayerSpawner script (SpawnPlayer function):

private void SpawnPlayer()
{
if (hasSpawned)
{
Debug.Log("PlayerAlreadySpawned*******");
return;
}

if (inGame)
{
if (GhostIDManager.Instance.ghostID == PhotonNetwork.NickName)
{
// Spawning the ghost's network body
ghostNetworkBody = PhotonNetwork.Instantiate(ghostNetworkBodyPrefab.name, playerHead.transform.position, playerHead.transform.rotation);
ExitGames.Client.Photon.Hashtable playerProperties = new ExitGames.Client.Photon.Hashtable();
playerProperties.Add("Spawned", true);
PhotonNetwork.LocalPlayer.SetCustomProperties(playerProperties);

hasSpawned = true;
}
else
{
// Spawning the player's network body
playerNetworkBody = PhotonNetwork.Instantiate(playerNetworkBodyPrefab.name, playerHead.transform.position, playerHead.transform.rotation);
ExitGames.Client.Photon.Hashtable playerProperties = new ExitGames.Client.Photon.Hashtable();
playerProperties.Add("Spawned", true);
PhotonNetwork.LocalPlayer.SetCustomProperties(playerProperties);

hasSpawned = true;
}
}
else
{
// Spawning player's network body in the menu scene
playerNetworkBody = PhotonNetwork.Instantiate(playerNetworkBodyPrefab.name, playerHead.transform.position, playerHead.transform.rotation);
ExitGames.Client.Photon.Hashtable playerProperties = new ExitGames.Client.Photon.Hashtable();
playerProperties.Add("Spawned", true);
PhotonNetwork.LocalPlayer.SetCustomProperties(playerProperties);

hasSpawned = true;
}
}