Search Unity

Returning to Lobby and starting a new game problem.

Discussion in 'Multiplayer' started by cephalo2, Dec 16, 2016.

  1. cephalo2

    cephalo2

    Joined:
    Feb 25, 2016
    Posts:
    263
    So I had some non-network related problems with scene changes that I resolved, but I have one more problem that does pertain to networking. This is a single player or two player game, for now I'm just connecting locally in a single player mode.

    I can start a game no problem, everything works, and then exit to the main lobby scene.

    When I try to start a new game again, the server can send a message to the new client, but I get this error when I try to send a message from client to server.

    Local invoke: Failed to find local connection to invoke handler on [connectionId=0] for MsgId:100
    UnityEngine.Networking.NetworkClient:Send(Int16, MessageBase)
    MyNetworkManager:ServerToClientGreeting(NetworkMessage) (at Assets/Scripts/MyNetworkManager.cs:114)
    UnityEngine.Networking.NetworkIdentity:UNetStaticUpdate()

    This only happens after I have started a game, quit to lobby scene and then tried to start a new game.

    It's as if I didn't clean something up when returning to the lobby. Any ideas?

    I'm a little confused as to the role of 'Game Player' and 'Lobby Player' prefabs. I just have empty scripts that print a message when they are created and destroyed. The 'Game Player' prefab does not appear to be used at all. The 'Lobby Player' seems to be created and destroyed as expected.
     
  2. MrLucid72

    MrLucid72

    Joined:
    Jan 12, 2016
    Posts:
    983
    I don't know the answer, but random spurts of ideas:
    • Skip to 13:00 >>

    • What I recently realized is that when you disconnect from a match (even while still within a lobby), the entire scene gets recreated. Maybe something didn't re-init? Or maybe you have TWO of something if you put dont destroy? I discovered all my serializations would detach and randomly had 2 network managers when i tried dont destroy on load.
    • LobbyPlayer should have a NetworkLobbyManager class or component attached to it.
    • GamePlayer should have a NetworkGamePlayer class attached to it.
     
  3. cephalo2

    cephalo2

    Joined:
    Feb 25, 2016
    Posts:
    263
    Hmm, I had assumed that the NetworkLobbyManager would need to be don't destroy on load so you still have your connections when the playScene is loaded. Maybe I did end up with two. Now I'll have to wait til after the Holidays to check. Thanks though!
     
  4. MrLucid72

    MrLucid72

    Joined:
    Jan 12, 2016
    Posts:
    983
    I thought so too, but recently I discovered that my dontDestroy is a different instance! I don't know if this is a bug or if it's supposed to do this because there's no devs on this forum to answer Q+A :(
     
  5. lejean

    lejean

    Joined:
    Jul 4, 2013
    Posts:
    392
    I had the same problem and I believe it was because I was trying to access the gamenetwork client that loaded with the game scene, but because my player objects already existed before the gamescene was loaded, it couldn't find it and failed to send the messages.

    I made a coroutine to suspend the code untill it had found the object it needed, and then send the messages.

    Also player prefab is not used, just leave it empty, but do check auto create player.
     
  6. lejean

    lejean

    Joined:
    Jul 4, 2013
    Posts:
    392
    Did you make your lobbymanager a singleton?

    Code (CSharp):
    1. public static LobbyNetworkManager instance = null;
    2.  
    3. private void Awake() {
    4.         //Check if instance already exists
    5.         if (instance == null) {
    6.             //if not, set instance to this
    7.             instance = this;
    8.         }
    9.         //If instance already exists and it's not this:
    10.         else if (instance != this) {
    11.             //Then destroy this. This enforces our singleton pattern, meaning there can only ever be one instance of a GameManager.
    12.             Destroy(gameObject);
    13.         }
    14.  
    15.         DontDestroyOnLoad(gameObject);
    16.     }
     
  7. cephalo2

    cephalo2

    Joined:
    Feb 25, 2016
    Posts:
    263
    Nope! I bet that's the issue right there. Yes, it's a singleton, but it does not check if it already exists. I'll get back if that's the issue.

    EDIT: I was mistaken. I do in fact check if it already exists in my Start() method, so I don't know where the problem is. My MyNetworkManager class inherits from NetworkLobbyManager, and if I use an Awake() method at all, I get the following error:

    NetworkManager detected a script reload in the editor. This has caused the network to be shut down.
    UnityEngine.Networking.NetworkIdentity:UNetStaticUpdate()

    I also noticed that I am NOT getting multiple MyNetworkManagers, so I don't know what the problem could be.
     
    Last edited: Dec 27, 2016
    MrLucid72 likes this.
  8. cephalo2

    cephalo2

    Joined:
    Feb 25, 2016
    Posts:
    263
    This is interesting. How did you detect if it found the object? I wonder if the handlers are still registered for the old client that isn't valid anymore.
     
    Last edited: Dec 27, 2016
  9. cephalo2

    cephalo2

    Joined:
    Feb 25, 2016
    Posts:
    263
    The problem happens in this method initially:

    Code (CSharp):
    1.     void ServerToClientGreeting(NetworkMessage msg)
    2.     {
    3.         StringMessage strMessage = msg.ReadMessage<StringMessage>();
    4.         print(this.GetInstanceID() + " :I the client at " + client.connection.address.ToString() + " have recieved the following message - '" + strMessage.value + "'");
    5.  
    6.         StringMessage reply = new StringMessage("I am the client at " + client.connection.address.ToString());
    7.         client.Send((short)NetworkMessageType.ClientToServerGreeting, reply);//this fails on second play
    8.        
    9.     }
    10.  
    I am responding to a greeting message from the server, and trying to send a reply from the client. The 'client' instance seems exactly the same in every way on the second play as it does on the first play.

    When I look at source code for NetworkManager etc. online, I see lots of Debug.Log statements that might be helpful, but I don't see those in my console. Is there a way I can turn those on? I'm not sure how to diagnose this problem.
     
  10. cephalo2

    cephalo2

    Joined:
    Feb 25, 2016
    Posts:
    263
    After looking at some source code I found online, the error happens in NetworkServer.cs, basically when the m_localConnection private variable is null. This variable is populated in the AddLocalClient method, which the comments say is called by the LocalClient. In LocalClient, AddLocalClient is called in the
    InternalConnectLocalServer method, and I can't find where that is called. Anybody know?

    EDIT: After some digging I can see that this method is called eventually from StartHost(), but I can't see anything in that chain that could cause it to fail or not be called. I am thoroughly confused.

    EDIT:Ok, I am finally getting somewhere I think. The clientScene is what creates the client with the ConnectLocalServer method. I noticed that when I used the SceneManager.activeSceneChanged method and printed a message when the scene changed, that lobbyScene was set 3 times in rapid succession! I was changing the scene once unnecessarily, but when I commented that out it still happened twice when I disconnect the client when the user chooses to quit to the main menu. I think the NetworkLobby package might be changing the scene an extra time, throwing off the connection.

    EDIT: I noticed that the scene changes to the lobbyScene automatically when the client disconnects. When I call StopHost during the OnClientDisconnect handler, it changes the scene a second time. If I don't call it though, then StartHost will then fail. Maybe I need to call StopHost somewhere else.

    EDIT: What I tried next was to simply call StopHost when the user quits to main, instead of disconnecting the client. This gets rid of the extra scene changes, but then I'm back to square one with the original error message.
     
    Last edited: Dec 28, 2016
  11. cephalo2

    cephalo2

    Joined:
    Feb 25, 2016
    Posts:
    263
    So I solved the issue, even though it was somewhat unsatisfying. The problem is that you can't just call StartHost and then StopHost and then call StartHost again. There are too many moving parts that come unglued. Here is the solution:

    First you have to UNcheck the Dont Destroy On Load option in the NetworkLobbyManager, otherwise you don't have control over the objects life cycle.

    Then in the Start method you manually destroy the old object while preserving the new, which I think lejean was trying to tell me but I didn't understand it at the time.
    Code (CSharp):
    1.     void Start ()
    2.     {
    3.         if (Instance != null)
    4.         {
    5.             Destroy(Instance);//destroy the old instance in favor of the new
    6.         }
    7.         Instance = this;//keep the new!
    8.         DontDestroyOnLoad(gameObject);//preserve for subsequent playScenes
    9.  
    10.    }
    11.  
    What I was doing was trying to keep the old instance and prevent the creation of the new, and that didn't work. Apparently you need a whole new NetworkLobbyManager each time you return to the main menu.
     
    mzinn and jamaster96 like this.