Search Unity

  1. Unity 2019.1 beta is now available.
    Dismiss Notice
  2. The Unity Pro & Visual Studio Professional Bundle gives you the tools you need to develop faster & collaborate more efficiently. Learn more.
    Dismiss Notice
  3. We're looking for insight from anyone who has experience with game testing to help us better Unity. Take our survey here. If chosen to participate you'll be entered into a sweepstake to win an Amazon gift card.
    Dismiss Notice
  4. Want to provide direct feedback to the Unity team? Join the Unity Advisory Panel.
    Dismiss Notice
  5. Unity 2018.3 is now released.
    Dismiss Notice
  6. Improve your Unity skills with a certified instructor in a private, interactive classroom. Watch the overview now.
    Dismiss Notice

Unity Multiplayer SpawnWithClientAuthority NetworkConnection is not ready

Discussion in 'Connected Games' started by paulsohops, Mar 28, 2018.

  1. paulsohops

    paulsohops

    Joined:
    Apr 16, 2014
    Posts:
    2
    I am trying out the Network Lobby asset (https://assetstore.unity.com/packages/essentials/network-lobby-41836) and running into an issue with SpawnWithClientAuthority. My linked player prefab has the following code:

    Code (CSharp):
    1. public GameObject Piece;
    2.  
    3. public override void OnStartLocalPlayer() {
    4.     CmdSpawnPiece();
    5. }
    6.  
    7. [Command]
    8. void CmdSpawnPiece()
    9. {
    10.     GameObject piece = Instantiate(Piece);
    11.     NetworkServer.SpawnWithClientAuthority(piece, connectionToClient);
    12. }
    But, once two players have joined a game through the lobby (with one acting as host), I get the following error on the hosting player:

    "SpawnWithClientAuthority NetworkConnection is not ready! UnityEngine.Networking.NetworkServer:SpawnWithClientAuthority(GameObject, NetworkConnection)"

    It worked fine before I was using the NetworkLobbyManager, with just the basic NetworkManager and NetworkMangerHud. What seems to be happening is when the scene is changes from the lobby scene to the main scene, the hosting player's connection is not set to ready (through ClientScene.Ready() or something) before OnStartLocalPlayer is called.

    Is there a function I can override in my player prefab NetworkBehavior class that will get called after the connection is set to ready, or is there an alternative way to spawn objects for players after they join? Thanks for the help!
     
  2. paulsohops

    paulsohops

    Joined:
    Apr 16, 2014
    Posts:
    2
    I did some digging around and think the right way to go about this is something like this:
    Code (CSharp):
    1. [Command]
    2. void CmdSpawnPiece()
    3. {
    4.     if (connectionToClient.isReady) {
    5.         GameObject piece = Instantiate(Piece);
    6.         NetworkServer.SpawnWithClientAuthority(piece, connectionToClient);
    7.     } else {
    8.         connectionToClient.RegisterHandler(MsgType.Ready, OnReady);
    9.     }
    10. }
    11.  
    12. void OnReady(NetworkMessageDelegate msg)
    13. {
    14.     GameObject piece = Instantiate(Piece);
    15.     NetworkServer.SpawnWithClientAuthority(piece, connectionToClient);
    16. }
    However, there seems to be an issue with this approach because of the engine code here: https://bitbucket.org/Unity-Technol...leviewer=file-view-default#ClientScene.cs-299

    In ClientScene.Ready, there is this code:
    Code (CSharp):
    1. var msg = new ReadyMessage();
    2. conn.Send(MsgType.Ready, msg);
    3. s_IsReady = true;
    4. s_ReadyConnection = conn;
    5. s_ReadyConnection.isReady = true;
    6. return true;
    It looks like the Ready message is being sent to the connection before isReady is set to true. So in my code snippet above, I would catch the message with OnReady, try to do SpawnWithClientAuthority, and get an error because the connection's isReady is still false.

    I've put in a workaround for now where I'm firing a custom message from my NetworkLobbyManager.OnLobbyClientSceneChanged (which is called after the NetworkManager's base
    OnClientSceneChanged is called and the connection is set to ready), and that's the message I'm registering against to spawn my stuff.
     
    Nigey likes this.
  3. Nigey

    Nigey

    Joined:
    Sep 29, 2013
    Posts:
    1,069
    Is this work around still okay for you? It's happening to me too. I'm pretty surprised there such a basic bug in their source code.
     
  4. thedrhax14

    thedrhax14

    Joined:
    Aug 7, 2014
    Posts:
    22
    I managed to use IEnumerator to workaround it. Here is my code:
    Code (CSharp):
    1. void Start() {
    2.     Debug.Log("[OnlinePlayer] Started");
    3.     CmdSpawnController();
    4. }
    5.  
    6. [Command]
    7. public void CmdSpawnController() {
    8.     Debug.Log("[OnlinePlayer] Spawning " + Team + " controller");
    9.     if (connectionToClient.isReady) {
    10.         Spawn();
    11.     } else {
    12.         StartCoroutine(WaitForReady());
    13.     }
    14. }
    15.  
    16. IEnumerator WaitForReady() {
    17.     while (!connectionToClient.isReady) {
    18.         yield return new WaitForSeconds(0.25f);
    19.     }
    20.     Spawn();
    21. }
    22.  
    23. [Server]
    24. void Spawn() {
    25.     GameObject controller = Instantiate(chosenController);
    26.     NetworkServer.SpawnWithClientAuthority(controller, connectionToClient);
    27. }
    This code is on my game player object, which is set in my network manager.
     
    Nigey likes this.
  5. Kirchesch

    Kirchesch

    Joined:
    Oct 17, 2017
    Posts:
    2
    What this [Server] do? why not re-calling CmdSpawnController()?