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?

Comments

  • carmine
    Options
    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.
  • 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]
  • Tobias
    Options
    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)...
  • 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)...
    Tobias, you can see the previous order in the first topic post - yes, RPC will be ignored if it is called before message queue is turned on. The strange thing is another point - using Update() instead of OnPhotonPlayerConnected()
  • Tobias
    Options
    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.
  • 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.
    I've prepared a reproduction project and it's zip file is around 1Mb - how can I send it to you? The forum accepts only below 256Kb.
  • Tobias
    Options
    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.
  • Tobias
    Options
    :D
    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.
  • 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).
    Oops! I should read docs more carefully, thanks for the tip!
    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).
    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! :?
    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.
    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?
  • Tobias
    Options
    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!
    Random matchmaking picks the oldest room first, yes. The idea is to fill up rooms as soon as possible. If you only create rooms when none is available, this should do a good job.
    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?
    Yes, if someone wants to select a room manually, then you need the lobby. In that case, auto-named rooms look a bit bad, cause they get a guid as string. Not very helpful ;)
  • 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.
    What means "region"? A cloud cluster defined by a specific server (currently US, Europe and Asia)? Does it mean that people from US can not play with people from Europe? Even with manual match making?
    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.
    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?
  • 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)
  • Sarah wrote:
    Just since last week you are able to select a region for your application. It is not available for Indie subscriptions.
    And what is the behaviour for Indie subscriptions? All regions are included and are shared between all users?
  • Tobias
    Options
    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.