Checking when all players have loaded in and then creating an array
The whole answer can be found below.
Try Our
Documentation
Please check if you can find an answer in our extensive documentation on PUN.
Join Us
on Discord
Meet and talk to our staff and the entire Photon-Community via Discord.
Read More on
Stack Overflow
Find more information on Stack Overflow (for Circle members only).
Checking when all players have loaded in and then creating an array
xxjon54xx
2021-05-29 01:40:45
Hi everyone,
I've been working on a project using PUN recently, and need to be able to check when all player prefabs have been instantiated in the scene in order to get the player object and script. Below is how I am seeing if all player prefabs have been instantiated or not.
The main issue I'm having is that the check for all players loading in does not work all the time, even when all player prefabs have been instantiated. I'm using a few custom-made scripts from an open-source project that is instantiating the prefab across the network using PhotonNetwork.Instantiate(), so it's possible that one of the issues stems from there.
Comments
There is a callback that is called when players join.
In it, check if all players are there and if you can start.
The Asteroids Demo in PUN 2 uses this together with a "ready" button. This can be used as "loaded" info, too.
Hi Tobias,
Thank you for the response :) I did narrow down the issue to players not always instantiating across clients (but sometimes they do and everything works fine). Below I'll explain how the "Start game" button functions across clients in the main menu scene and how players get to the game scene.
This function is attached to the Start game button I have in Unity, which closes the room being accessible to clients across the network and then calls the function "InitLoadLevel()" for the master client.
InitLoadLevel is a game object attached with a PhotonView, which then calls the RPC towards the script AsyncManager so all players then call the method on their client. AsyncManager is as follows:
This loads the game scene across clients asynchronously, which works fine. The problem then becomes how the player is instantiated in the scene across clients. In the game scene I have a game object called "Game Room Manager," which then makes the call to instantiate the player (this is the last of the process from the main menu scene to instantiating the player character).
What's odd is this sometimes works for certain players, but not for others. In particular, it becomes more prone to breaking when there is either 3 or 4 clients in the room. I could try and go back to using PhotonNetwork.AutomaticallySyncScene = true; and PhotonNetwork.LoadLevel(), however one of the issues I was having back then is that sometimes the game would freeze for certain clients when attempting to load the game scene. This asynchronous method is more reliable, but seems to drop clients from the room at times. The version of PUN I am currently on is Pun: 2.26 Photon Lib: 4.1.4.8. Appreciate if you read through all of this and are able to get back to me :smile:
Update: It seems that the player instantiation is called across the network on one client for each player that is in the room, but not the other way around (i.e. one client will have both their character instantiate along with the other players in the room, but other clients do not instantiate other players in the scene). It seems whoever loads the game scene first gets all instantiation calls across the network, but those loading when an instantiation call happens do not receive it on their client (and thus certain players do not instantiate within the scene). I am thinking of 2 possible solutions to tackle this issue of instantiation across clients:
Follow the Asteroids demo and create a buffer time of 5 seconds to allow players to load the scene, then have each client call the CreateController() function so that the instantiation call doesn't occur while a client may be loading.
Create an RPC that increments upon a client completing loading of the game scene, and when it is equal to the number of players in the room then CreateController() is called on each client and thus instantiation does not occur while a player may be loading the game scene.
The potential problems of each solution is that one client could take longer than 5 seconds to load the game scene, and the other is that the RPC is not received while a client is loading (bufferedviaserver might help here, but with the current instantiation call being dropped as it is I'm not sure if there is a fool-proof solution). I'll experiment around and see what works best and if the bug remains.
When you load a scene in Unity this will destroy all objects before activating the scene. I assume your clients all create the objects but one client then loads.
This might help:
https://doc.photonengine.com/en-us/pun/v2/gameplay/rpcsandraiseevent#timing_for_rpcs_and_loading_levels