Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.

Question Problem Spawning Objects, help!

Discussion in 'Netcode for GameObjects' started by GuirieSanchez, Nov 7, 2022.

  1. GuirieSanchez

    GuirieSanchez

    Joined:
    Oct 12, 2021
    Posts:
    355
    I was following a deprecated UNET tutorial (this one), in which they use a NetworkManager that spawns PlayerObjects (GO with a non-physical entity in the game) for each client connected to the server (so far, it works exactly the same as in "netcode for GameObjects"). Then, each PlayerObject spawns its PlayerUnit (with a physical presence in the game) by instantiating the PlayerUnit and then using a
    [Command]
    for the server to spawn it.

    The way it's done in the tutorial is by checking whether the PlayerObject is
    (IsLocalPlayer)
    , and if so, then uses the [Command] (for instance,
    CmdSpawnMyUnit();
    ), in which function spawns the unit on each client as follows:

    Code (CSharp):
    1.  
    2. [Command]
    3. void CmdSpawnMyUnit()
    4.     {
    5.            GameObject go = Instantiate(PlayerUnitPrefab)
    6.        
    7.            NetworkServer.Spawn(go);
    8.  
    9.     }
    10.  
    The equivalent for a netcode for gameobjects version would be to call a ServerRpc and spawn the PlayerUnit in a relatively similar fashion:

    Code (CSharp):
    1.  
    2. [ServerRpc]
    3. private void SpawnGameManagerServerRpc()
    4.     {
    5.  
    6.         if (!IsLocalPlayer) return;
    7.    
    8.         GameObject go = Instantiate(PlayerUnitPrefab);
    9.  
    10.         //Propagate it to all the clients (and wire up the NetworkIdentity)
    11.  
    12.         go.GetComponent<NetworkObject>().Spawn();
    13.         go.GetComponent<NetworkObject>().ChangeOwnership(this.NetworkObjectId);
    14.  
    15.  
    16.     }
    My guess is that the results should be the same: as in the tutorial, you have on every PC (or client connected to the server) a copy/clone of the PlayerUnit, as you do with the PlayerObjects that get spawned by the NetworkManager.

    However, this is not the case. I don't know whether it's something to do with
    (IsLocalPlayer)
    (although I believe it's not) or with the ServerRpc, but I'm only getting a single copy of the PlayerUnit instead of as many as PlayerObjects are.

    PS: The prefabs to spawn have their proper "Network Object" component and are included in the NetworkManager's list for spawning.

    PS2: As a side issue I'm facing, I was expecting this line of code
    go.GetComponent<NetworkObject>().ChangeOwnership(this.NetworkObjectId);
    to give that GameObject some kind of authority that could be checked by using (IsOwner), so that I can run something like:
    if (!IsOwner) Destroy(this);
    . However, it also does not work.
     
    Last edited: Nov 8, 2022
  2. cerestorm

    cerestorm

    Joined:
    Apr 16, 2020
    Posts:
    460
    You need to do the IsLocalPlayer check on the client, if you put it in the ServerRpc that check is happening on the server so it will only be true for the host.
     
    GuirieSanchez likes this.
  3. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    2,110
    Why aren‘t you following non-deprecated Netcode tutorials?
     
  4. GuirieSanchez

    GuirieSanchez

    Joined:
    Oct 12, 2021
    Posts:
    355
    You're completely right, that did it. However, I think I'm missing the concept of ServerRpc. Isn't the ServerRpc run by the server/host? so the check was misplaced, of course, but now that I think about it, I would expect the
    (IsLocalPlayer)
    to be true for every single client since it's the Server itself that runs the Rpc and then applies it to the clients. But again, I clearly have to continue studying network basics, as this demonstrates. Thanks for the help!

    There are 4 tutorials on network for gameobjects that I'm aware of (supported by Unity), but none of them are as clear or go as deep as this one (at least for my purposes).

    btw, does anyone have any idea about this?
     
  5. cerestorm

    cerestorm

    Joined:
    Apr 16, 2020
    Posts:
    460
    ChangeOwnership needs a clientId, but you can save yourself a step and use SpawnWithOwnership(clientId) instead of Spawn().

    CodeSmile is right you need to be following up-to-date tutorials or you're making life more difficult for yourself. Take a look at the ones by Tarodev and CodeMonkey.
     
    marce155 and GuirieSanchez like this.
  6. GuirieSanchez

    GuirieSanchez

    Joined:
    Oct 12, 2021
    Posts:
    355
    I checked Tarodev, CodeMonkey, Dapper Dinos, and Dilmer's. But they all teach one specific use case for the netcode, so I had to go ahead and look for something else.

    Btw just before reading the answer I checked in the doc this SpawnWithOwnership and tried out, but to no avail :(

    The code is the following:

    Code (CSharp):
    1. GameObject go = Instantiate(gOPrefab);
    2. go.GetComponent<NetworkObject>().SpawnWithOwnership(OwnerClientId);
    But then, once the GameObject is instantiated (and spawned), in its Awake function I use:
    if (!IsOwner) Destroy(this.gameObject);


    I would expect all other instantiated and spawned game objects to be destroyed, and leave on the scene the only one that the PlayerObject has ownership over. However, every single copy gets destroyed.
     
  7. cerestorm

    cerestorm

    Joined:
    Apr 16, 2020
    Posts:
    460
    I'm pretty sure Awake is too early and IsOwner won't be valid yet.
     
    GuirieSanchez likes this.
  8. GuirieSanchez

    GuirieSanchez

    Joined:
    Oct 12, 2021
    Posts:
    355
    That makes sense.

    If I remember correctly, I think there's a callback to check whether ownership has been changed. Maybe I can try that out.

    EDIT: for the time being, I moved the
    if (!IsOwner) Destroy(this.gameObject);
    piece of code to the Start function.
    And now something weird happens: nothing gets destroyed. Not the game object spawned with ownership (as it should), but nor any of the other game objects in the scene.
     
    Last edited: Nov 8, 2022