Search Unity

Resolved Why Won't My Player Spawn?

Discussion in 'Multiplayer' started by Boomboyag, Nov 11, 2022.

  1. Boomboyag

    Boomboyag

    Joined:
    Oct 13, 2020
    Posts:
    33
    Hi! I've recently begun working on a multiplayer game, and was having trouble making my spawn system. What I'm trying to do is have the player "spawn" into the environment (aka spawn a first person controller that is owned by the person requesting the spawn). However, my code simply will not fire, even when hosting. I hae no idea what I'm doing wrong and would greatly appreciate any help.

    If I need to clarify anything please let me know.

    My Code:
    Code (CSharp):
    1. public class Player_Spawn_UI : NetworkBehaviour
    2. {
    3.     [SerializeField] Button spawnButton;
    4.     [SerializeField] GameObject menuObject;
    5.     [SerializeField] GameObject playerBody;
    6.  
    7.     private void OnEnable()
    8.     {
    9.         spawnButton.onClick.AddListener(() =>
    10.         {
    11.             SpawnPlayerBodyServerRpc();
    12.             menuObject.SetActive(false);
    13.         });
    14.     }
    15.  
    16.     [ServerRpc(RequireOwnership = false)]
    17.     void SpawnPlayerBodyServerRpc()
    18.     {
    19.         GameObject playerObj = Instantiate(playerBody, Vector3.zero, Quaternion.identity);
    20.         playerObj.GetComponent<NetworkObject>().Spawn(true);
    21.         playerObj.GetComponent<NetworkObject>().ChangeOwnership(OwnerClientId);
    22.     }
    23. }
     
  2. RikuTheFuffs-U

    RikuTheFuffs-U

    Unity Technologies

    Joined:
    Feb 20, 2020
    Posts:
    440
    Hi @Boomboyag
    1. How are you instantiating the Player_Spawn_UI object?
    2. What does its inspector look like while in play mode?
    3. If you add a log at line 11, does it get printed in the console?
     
  3. Boomboyag

    Boomboyag

    Joined:
    Oct 13, 2020
    Posts:
    33
    Hi @RikuTheFuffs-U
    The Player_Spawn_UI is prebuilt into the scene, and is turned off/on by the local player

    upload_2022-11-11_6-52-39.png
    This is what the UI looks like when in-game.

    When adding a log in line 11 it was called. However, adding one in the server rpc did not do anything, even when playing as the host
     

    Attached Files:

  4. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    5,975
    I strongly advise against making UI networked. Use a proxy network object that is in-scene placed which does the communication part as well as show/hide any local (non networked) UI. That proxy should also handle all the UI callbacks.
     
    RikuTheFuffs-U likes this.
  5. RikuTheFuffs-U

    RikuTheFuffs-U

    Unity Technologies

    Joined:
    Feb 20, 2020
    Posts:
    440
    Thanks for the answer! I think the issue here is that the Player_Spawn_UI is not actually being treated as a Networked object by the system even though it's in the scene, which can be caused by a couple things.

    I just tried with the following setup and it works in host:

    This is your networked object:

    upload_2022-11-11_13-35-52.png

    Code (CSharp):
    1. using Unity.Netcode;
    2. using UnityEngine;
    3. using UnityEngine.UI;
    4.  
    5. public class Player_Spawn_UI : NetworkBehaviour
    6. {
    7.     [SerializeField] Button spawnButton;
    8.  
    9.     void OnEnable()
    10.     {
    11.         spawnButton.onClick.AddListener(() =>
    12.         {
    13.             SpawnPlayerBodyServerRpc();
    14.             gameObject.SetActive(false);
    15.         });
    16.     }
    17.  
    18.     [ServerRpc(RequireOwnership = false)]
    19.     void SpawnPlayerBodyServerRpc()
    20.     {
    21.         Debug.Log("X");
    22.     }
    23. }
    24.  
    And the button is on a separate, client-only canvas (so no NetworkObject on it).
    Now, if you play the scene, enter host mode, and then press the button that prints the log, everything should work. However when you exit PlayMode you'll notice a warning in your console:

    Code (CSharp):
    1. [Netcode] NetworkBehaviour-PlayerSpawnUI is being destroyed while NetworkObject-PlayerSpawnUI is still spawned! (could break state synchronization)
    This is because the PlayerSpawnUI object is already in the scene at startup. I'd recommend that it is is spawned through:

    Code (CSharp):
    1. var networkedObject = playerSpawnUIObject.GetComponent<NetworkObject>();
    2. networkedObject.Spawn(true);
    by the server when the player connects, instead of having it pre-laoded in the scene, to ensure state synchronization works properly.

    Does this setup work for you?
     

    Attached Files:

  6. Boomboyag

    Boomboyag

    Joined:
    Oct 13, 2020
    Posts:
    33
    Thank you both so much! Putting the script on a separate networked object worked! I just have one more small question. Do I have to set [ServerRpc(RequireOwnership = false)] to allow clients to spawn objects? In my previous testing I had to set ownership to false, otherwise an error would pop up saying that the client did not have correct permissions. Anyway, thank you all so much for your help! I really appreciate it!
     
  7. RikuTheFuffs-U

    RikuTheFuffs-U

    Unity Technologies

    Joined:
    Feb 20, 2020
    Posts:
    440
    Not really: what's important to understand is that you can only spawn networked objects from a method executed the server. [ServerRpc] are Invoked by the client and executed on the server, which is why you can spawn objects from there, but you will be able to do the same in any method that is called and executed on the server, even if they don't have the [ServerRpc] attribute