Search Unity

  1. Get all the Unite Berlin 2018 news on the blog.
    Dismiss Notice
  2. Unity 2018.2 has arrived! Read about it here.
    Dismiss Notice
  3. We're looking for your feedback on the platforms you use and how you use them. Let us know!
    Dismiss Notice
  4. The Unity Pro & Visual Studio Professional Bundle gives you the tools you need to develop faster & collaborate more efficiently. Learn more.
    Dismiss Notice
  5. Improve your Unity skills with a certified instructor in a private, interactive classroom. Learn more.
    Dismiss Notice
  6. ARCore is out of developer preview! Read about it here.
    Dismiss Notice
  7. Magic Leap’s Lumin SDK Technical Preview for Unity lets you get started creating content for Magic Leap One™. Find more information on our blog!
    Dismiss Notice
  8. Want to see the most recent patch releases? Take a peek at the patch release page.
    Dismiss Notice

Network players disappear from hierarchy on new scene load? Unet

Discussion in 'Connected Games' started by larswik, Aug 3, 2018.

  1. larswik

    larswik

    Joined:
    Dec 20, 2012
    Posts:
    256
    As the title mentions my problem, I found a fix but I think my fix is causing other issues on the new level. I wanted to make sure that my fix is a correct way of doing it.

    When the server/client clicks a button this code is called and successfully loads the new scene.
    Code (CSharp):
    1.  
    2. if(NetworkServer.active){
    3.    GameObject.Find("LobbyManager").GetComponent<LobbyManager>().ServerChangeScene("desert");
    4. }
    This loads the new scene on both host and client. But the network players disappear, looks like they are getting destroyed when the new scene loads. To fix this I added this DontDestroyOnLoad() when the networkPlayers are instantiated on their script.
    Code (CSharp):
    1. void Start () {
    2.     DontDestroyOnLoad(this.gameObject);
    3. }
    But now on the new level I am having problems with the NetworkServer.Spawn() not spawning any object on the host or client machines? Each side has a 2D castle that each player can relocate their position. But they are not even being created.

    This is called in the Awake() method of the game controller in the new scene.
    Code (CSharp):
    1.     [Command]
    2.     public void Cmd_setUpMapNetwork(string level){
    3.         Debug.Log("The load type is: " + level);
    4.         if(level == "winter"){
    5.             GameObject casRight = Instantiate(WinterCastleRight);
    6.             GameScript.levelCastleRightScript = casRight.transform.GetChild(0).GetComponent<cannonController>(); // pass this to the GameScript Objects to use.
    7.             casRight.name = "CastleRight";
    8.  
    9.             GameObject casLeft = Instantiate(WinterCastleLeft);
    10.             GameScript.levelCastleLeftScript = casLeft.transform.GetChild(0).GetComponent<CannonLController>(); // pass this to the GameScript Objects to use.
    11.             casLeft.name = "castelLeft";
    12.  
    13.             NetworkServer.Spawn(casRight);
    14.             NetworkServer.Spawn(casLeft);
    15.         }
    16.     }
    Any help is appreciated.

    Thank you!
     
  2. csofranz

    csofranz

    Joined:
    Apr 29, 2017
    Posts:
    44
    By default, the network manager is set up to spawn the local players when the level starts up, each with local authority on their respective machines. This usually means that you get a new player prefab for each new level for each connected client.

    The way you are doing it in above example will probably not work because you are spawning both players as server objects, none with local authority (i.e. these objects are server objects, not player objects, and hence can't be controlled by the players). You should instead spawn single player objects as commands (e.g. during OnStartClient) from the connected client, since you then also have the connectionID you need to assign authority to. Think of it this way: in your example, what would happen if one player disconnects prior to execution of the command? The command would still (incorrectly) spawn left and right castle, even though there is only one player present. To which player would you assign authority of the second castle?

    Hope this helps,
    -ch
     
  3. larswik

    larswik

    Joined:
    Dec 20, 2012
    Posts:
    256
    Hey csoFranz, I took the weekend off to let my brain rest, this Networking has been driving me nuts.

    I see what you are saying about spawning this GO on the server and should be spawned by the client on the OnStartClient(). Those castles that they are spawning are like cheese pieces, the player can control it, but that is not the player itself.

    What I don't understand is that when I start the game from the LobbyManager, it launches my map room scene, which they pick the game level to play on. In the Hierarchy I can see the 2 network players created by the LM, but once the host selects the level to play and launches the next scene both of the network players get destroyed and new ones are not created for the next level automatically? So I can not use the OnScreenClient() if the network players get destroyed. So is the correct thing to do when a network player is created to put a DoNotDestroyOnLoad() to keep it around as you load new scenes, or to create a new network players for the new scene and let the other ones get destroyed?

    A assumed that I was not able to spawn those castle GameObjects because when I loaded a new scene, those network players in the Hierarchy got detached from the new scene, and didn't know where to spawn the castles.

    I hope what I wrote made sense. :)
     
  4. csofranz

    csofranz

    Joined:
    Apr 29, 2017
    Posts:
    44
    Lars,

    I currently don't have access to my dev machine, so everything I write is from Memory. I'll try and confirm when I get back.

    IIRC, the Lobby Manager allocates Lobby Players during matchmaking - These are not correct Player objects, and they get allocated from lobbyPlayerPrefabs when Players connect to a host, and destroyed when they disconnect, or when the Network Level is loaded. The LobbyManager will be the only object that carries over from other Levels (DontDestroyOnLoad). This may become a problem later when you re-renter your lobby, but let's cover one issue at a time :) .
    After loading a new level, the LobbyManager (which I believe is an instance of the Network Manager) instantiates Player objects from the playerPrefabs (not Lobby prefabs), and issues them correct authority - provided that you have enabled auto-spawing players.

    So you may want to check the following:
    - you have defined playerPrefabs and filled the correct slot in the Lobby Manager
    - made sure you have the correct (use the Default) lobbyPlayer objects
    - enable auto-spawning Players from the prefabs

    This should ensure that you correctly spawn new Player objects with each Level.

    Cheers,
    -ch
     
  5. larswik

    larswik

    Joined:
    Dec 20, 2012
    Posts:
    256
    Thanks for sticking in there with me cosfranz as I am figuring this out.

    So what you described is basically what I have. I have the playerPrefabs connected to the LobbyManager and auto-spawning checked. When both player join the countdown happens and the LobbyManager starts the game. Both players are then sent to the Map Room Scene, which is the LobbyManager gameScene. I can see the 2 playerPrefabs in the hierarchy that were auto spawned.

    But after this point lies my problem. The host/client player selects a UIButton which loads the next scene photo 3, and is where the battle (game play) happens. I included a photo and you can see the Map room Scene 2 and you can see the playerPrefab is created with the red arrow, but there is only one playerPrefab right now, I didn't create a seperate build to demonstrate 2 playerPrefabs for this issue.

    The player clicks one of the buttons and it loads the next scene which is photo 3. Attached to the button is this code.
    Code (CSharp):
    1.  
    2. if(NetworkServer.active){
    3.     GameObject.Find("LobbyManager").GetComponent<LobbyManager>().ServerChangeScene("desert");
    4. }
    Now both Playersprefab get the ServerChangeScene and both switch to the next scene, photo 3 in this example. But, as you can see in the scene 3 photo, in the Hierarchy, the new scene is loaded but the playerPrefab is destroyed, as to be expected on a new scene load. But the playerPrefab or prefabs needs to stick around to play the next scene I would think?

    So if I have explained myself correctly you can see where I am stuck. I don't think the multiplayer game can continue without playerPrefabs, those are the links to the players in the real world. So would I add Don'tDestroyOnLoad to my playerPrefabs to keep them around when Scene 3 loads, so they are not destroyed? Also, would they be connected to that new loaded scene and be able to spawn objects in to it.

    So this is where my grey hair is coming from at the moment. If you can help me get passed this I would be very thankful!
     

    Attached Files:

  6. csofranz

    csofranz

    Joined:
    Apr 29, 2017
    Posts:
    44
  7. larswik

    larswik

    Joined:
    Dec 20, 2012
    Posts:
    256
    Hey, that first link ServerChangeScene I have read many times, but this line was confusing in the description.
    Not ready means it is deleting the playerPrefabs, so how could I make them ready I was thinking? Also the line after says.
    I assumed the 'Clients' were the playerPrefabs, so how can I make them ready if they are deleted, again confusing? So I am coming to the understanding that the clients are not the playerPrefabs?

    The second link you sent I have not seen, and I think this is the missing link I need to move forward. So that code needs to be on a script that derives from LobbyManager, which derives from NetworkManager which should located on a GO on new scene that loads.

    Thanks cosfranz. I will see what happens over the next couple of days as I have time to work on it. Hopefully the second link you sent will push me forward on the game, it has been very frustrating and I am very thankful for your continued help!
     
  8. csofranz

    csofranz

    Joined:
    Apr 29, 2017
    Posts:
    44
    In Networking Terms, the Client is usually the entire computer (or process) that is connected to the Server (computer). Each Player Computer is either the Client or Server (let's disregards self-Hosting for the Moment).

    In Unity Networking, each PlayerObject is nothing more than a GameObject representing each Player, usually created by instancing the Player prefab (one each for each Player). So if you have three Players, each Scene on each Client (Computer) has three different copies of a Player object, one for each Player connected. The one that represents you on your machine (and only on your machine) usually has 'local authority', meaning that scripts belonging to this (and only this) copy of the Player object may issue Commands to the Server (machine).

    Each time a new Scene is allocated, all objects are deleted, with the exception of those objects that have a Special flag set. If you Change a Level with three networked Player objects, These objects all get deleted upon loading the new Level. The entire Scene gets initialized by unity, and as one step of this process, the Client's (the entire machine's) Network Status is set to not-ready.