Game start synchronization
Options
What we have:
- two player network game
- main level
- lobby level
What we want:
Start the game in the main level for both players synchronously. In details:
- Player A creates a room from the lobby level and waits for an opponent. Ideally he will not leave the lobby level (not Photon's lobby!) until the opponent is found.
- Player B finds a room of player A and joins it.
- Once two players became aware of each other the game starts automatically on the main level.
How we try to achieve this:
- Inside the lobby we handle OnPhotonPlayerConnected() event like this:
[code2=csharp]public void OnPhotonPlayerConnected(PhotonPlayer player)
{
if (PhotonNetwork.otherPlayers.Length > 0)
{
PhotonNetwork.isMessageQueueRunning = false;
Application.LoadLevel("Main");
}
}[/code2]
- Inside the main level we have a GO with the following code:
[code2=csharp]void Start()
{
photonView.RPC("OnRemoteGameStarted", PhotonTargets.Others, parameters);
OpenNetworkMenu(); // it means that a player will see a menu until the opponent loaded the main level also
PhotonNetwork.isMessageQueueRunning = true;
}
[RPC]
protected void OnRemoteGameStarted()
{
// the opponent tell us that he is ready to play and now we can start playing
// because if we a here then we already loaded the main level
CloseNetworkMenu();
}[/code2]
The problem is that when player B receives OnRemoteGameStarted() it happens before OnPhotonPlayerConnected() with true condition of "PhotonNetwork.otherPlayers.Length > 0". And player B fires the error "Received RPC "OnRemoteGameStarted" for viewID 2 but this PhotonView does not exist!".
How we can handle such scenario?
- two player network game
- main level
- lobby level
What we want:
Start the game in the main level for both players synchronously. In details:
- Player A creates a room from the lobby level and waits for an opponent. Ideally he will not leave the lobby level (not Photon's lobby!) until the opponent is found.
- Player B finds a room of player A and joins it.
- Once two players became aware of each other the game starts automatically on the main level.
How we try to achieve this:
- Inside the lobby we handle OnPhotonPlayerConnected() event like this:
[code2=csharp]public void OnPhotonPlayerConnected(PhotonPlayer player)
{
if (PhotonNetwork.otherPlayers.Length > 0)
{
PhotonNetwork.isMessageQueueRunning = false;
Application.LoadLevel("Main");
}
}[/code2]
- Inside the main level we have a GO with the following code:
[code2=csharp]void Start()
{
photonView.RPC("OnRemoteGameStarted", PhotonTargets.Others, parameters);
OpenNetworkMenu(); // it means that a player will see a menu until the opponent loaded the main level also
PhotonNetwork.isMessageQueueRunning = true;
}
[RPC]
protected void OnRemoteGameStarted()
{
// the opponent tell us that he is ready to play and now we can start playing
// because if we a here then we already loaded the main level
CloseNetworkMenu();
}[/code2]
The problem is that when player B receives OnRemoteGameStarted() it happens before OnPhotonPlayerConnected() with true condition of "PhotonNetwork.otherPlayers.Length > 0". And player B fires the error "Received RPC "OnRemoteGameStarted" for viewID 2 but this PhotonView does not exist!".
How we can handle such scenario?
0
Comments
-
I've had this happen a lot, and it's super frustrating to figure out.
One thing you can do is turn on and off "groups/channels" I do something like this:
[code2=csharp]public enum NetworkLevels:int
{
General = 0,
Chat = 1,
Player = 2,
AI = 3
}
PhotonNetwork.SetReceivingEnabled((int)NetworkLevels.Player, false);
PhotonNetwork.SetReceivingEnabled((int)NetworkLevels.AI, false);[/code2]
You'll notice the last parameter of PhotonNetwork.Instantiate is which network level. (this way your objects don't get put into previous scene)
Combine this with putting that isMessageQueueRunning = false ... code into "OnJoinRoom" instead of OnPlayerConnected.0 -
Actually, I got it working with 2 modifications:
1. I've changed OnPhotonPlayerConnected() to Update() and added extra if there:
[code2=csharp]public void Update()
{
if (PhotonNetwork.isMessageQueueRunning && PhotonNetwork.otherPlayers.Length > 0)
{
PhotonNetwork.isMessageQueueRunning = false;
Application.LoadLevel("Main");
}
}[/code2]
2. I've changed the sequence of method calls inside Start()
[code2=csharp]void Start()
{
OpenNetworkMenu(); // it means that a player will see a menu until the opponent loaded the main level also
PhotonNetwork.isMessageQueueRunning = true;
photonView.RPC("OnRemoteGameStarted", PhotonTargets.Others, parameters);
}[/code2]0 -
What was the previous order? Did you call the RPC while the message queue was off? Not sure if this would be working (if it's ignoring the RPC, it should print out an error or warning to the console)...0
-
Tobias wrote:What was the previous order? Did you call the RPC while the message queue was off? Not sure if this would be working (if it's ignoring the RPC, it should print out an error or warning to the console)...0
-
Hm. I can't reproduce the behavior of the first post. Either I do something wrong or the PUN code changed or it's timing related and I can't reproduce that.
If you want to, send me a reproduction project. Otherwise, as you worked around it, we can as well ignore this.
In any case: Thanks for trying to explain it. I'm sorry, I couldn't help more directly.0 -
Tobias wrote:Hm. I can't reproduce the behavior of the first post. Either I do something wrong or the PUN code changed or it's timing related and I can't reproduce that.
If you want to, send me a reproduction project.0 -
Ah, cool. Mail it to: developer@exitgames.com
Alternatively use minus.com or mediafire.com or something to upload the file, if you wanted to.0 -
Finally I can write a useful answer!
Thanks for the repro case.
I think the issue you have is more or less self made.
In the code you sent (without modification) you get the RPC errors because your never change the joining player into the second scene.
It's not a surprise that the player in scene one can't execute the RPCs - there is no photon view in it! Even if: It would not be the same as in the second scene ("Main").
Implement OnJoinedRoom (additionally) and in it, check the player count > 0. Pause the message queue and load the Main level (same code as in your OnPhotonPlayerConnected).
Aside from that, you should get rid of the joining code you use currently. At least, if the plan is to keep that logic: Join any room (first in lobby list).
Why? That code will make everyone get the list, then just pick the random game that currently on top and then any player joining at about the same time will fail due to that.
Much better:
Don't join the lobby at all! Use: PhotonNetwork.autoJoinLobby = false (read the doc! This causes other callbacks).
Let the server name your rooms (pass no room name to create room).
Use random matchmaking.
Set room maxPlayers.0 -
First of all, thanks for your time looking into my reproduction project!Tobias wrote:Implement OnJoinedRoom (additionally) and in it, check the player count > 0. Pause the message queue and load the Main level (same code as in your OnPhotonPlayerConnected).Tobias wrote:Aside from that, you should get rid of the joining code you use currently. At least, if the plan is to keep that logic: Join any room (first in lobby list).Tobias wrote:Much better:
Don't join the lobby at all! Use: PhotonNetwork.autoJoinLobby = false (read the doc! This causes other callbacks).
Let the server name your rooms (pass no room name to create room).
Use random matchmaking.0 -
demid wrote:I was always wondering which algorithm is used to find the matching random room? Will the server try first the oldest room or really random? Will it take into account geographic location of the master client and joining player? That's a good time to ask these questions!
Regions are totally separated from each other, so that's never in the matchmaking. You can't see another region's rooms in another lobby either.
All clients of one region should be built to connect to their fitting servers, if possible. In worst case, use only one region for all players worldwide. A bit better would be to let players pick their region by a setting.
We look into providing a master server address which is geo-location loadbalanced. This would get you on the closest master.demid wrote:About autonamed rooms for random matchmaking I fully agree with you - it's a better approach! Also I cut the named room creation/join stuff for reproduction project. As I understood I have to join lobby anyway if I want to have an option of joining to a named room, right?0 -
Regions are totally separated from each other, so that's never in the matchmaking. You can't see another region's rooms in another lobby either.In worst case, use only one region for all players worldwide. A bit better would be to let players pick their region by a setting.
So, as far as I understood from that topic no region management is available at this time, right?0 -
demid wrote:Probably I missed an important feature - where can I read about region management? I've also read this topic http://forum.exitgames.com/viewtopic.php?f=5&t=1948&p=9176&hilit=region#p9176.
So, as far as I understood from that topic no region management is available at this time, right?
Just since last week you are able to select a region for your application. It is not available for Indie subscriptions. The selection can be found on the subscription page.
You can subscribe to either all regions or just one (US, EU, Asia)0 -
Indie subscriptions include all regions, yes.
But regions are (always) completely separated from each other. Otherwise, the benefit of (more) local servers would be lost for some players due to matching.
If you want international matches, pick one region and connect to it. Both, "regional" and "international" games can be offered in one game - any way you want.0