How to run script on spawned object for clients in Unity?

193 views Asked by At

I am trying to understand some concepts in Unity.

I am spawning objects on the Host using :

GameObject player = Instantiate(playerPrefab, vector3, Quaternion.identity);
player.GetComponent<PlayerUiLoader>().LoadPlayer("Player 1");
player.GetComponent<NetworkObject>().Spawn();

The PlayerUiLoader is only here to display the name of the player above his head, and the script is nested on the playerPrefab.
Now, when i LoadPlayer, the clients don't see the name, but they see the spawned player.

Why the player spawned has not inherited his attributes / script before spawning ? What is the right way to do in these circumstances ?

Note : the player prefab here has a clientNetworkTransform and is transformed over the network, but the Network Transform script makes no changes, unfortunately (it was the first I have tried).

Edit : This is the LoadPlayer method, which is working fine on the Host for any player spawned :

public void LoadPlayer(string name)
    {
      username.text = name;
    }

Is the ClientRpc method the only one that can work in such situation ? Why the Network Object spawned doesn't inherit from the previously set attributes ?

1

There are 1 answers

3
VonC On BEST ANSWER

To make sure the player name is visible to all clients, you would need to synchronize the player's UI information across the network.
That can be achieved using a ClientRpc method.

In Unity's networking (assuming you are using Netcode for GameObject instead of the old Mid-Level API MLAPI), you can use [ClientRpc] to send updates from the server/host to all clients.

Modify the LoadPlayer method to call a ClientRpc method that updates the player name on all clients.

using Unity.Netcode;
using UnityEngine;
using UnityEngine.UI;

public class PlayerUiLoader : NetworkBehaviour
{
    public Text username; // Assuming you have a Text component for the player's name.

    public void LoadPlayer(string name)
    {
        if (IsServer) // Check if this is being executed on the server.
        {
            UpdatePlayerNameClientRpc(name);
        }
    }

    [ClientRpc]
    private void UpdatePlayerNameClientRpc(string name)
    {
        username.text = name;
    }
}

Do attach this script to your player prefab and link the username Text component accordingly.

+-----------------------+
|      Unity Host       |
| +-------------------+ |
| | GameObject player | |
| | + PlayerUiLoader  | |
| | + NetworkObject   | |
| +-------------------+ |
|        | |            |
| ClientRpc Update      |
|        V V            |
+-----------------------+
|       Clients         |
|   See updated name    |
+-----------------------+

When you want to set the player's name, call the LoadPlayer method. It checks if the code is running on the server and then invokes the ClientRpc method.

The UpdatePlayerNameClientRpc method is marked with the [ClientRpc] attribute, indicating that it is a method that the server calls to execute on all clients. It updates the username Text component with the provided name.

The IsServer check makes sure the ClientRpc method is only called by the server, which is necessary for proper synchronization in a multiplayer setting.

That should, when a player's name is set on the server, update it across all clients, synchronizing the displayed name in your multiplayer game.


Can you confirm that a spawned object doesn't inherit from his attributes set before the spawn?

Yes, you are correct: in Unity's Netcode for GameObjects, a spawned object does not automatically inherit its attributes set before the spawn across the network. The initial state of the object as seen by the clients is determined at the point of spawning. Changes made to the object on the server before it is spawned are not automatically propagated to the clients.

To synchronize these initial states or attributes across clients, you would indeed use network variables. Network variables are designed to automatically synchronize their values from the server to all clients.
By setting these variables before spawning the object, you make sure joining players receive the current state of these variables upon connection, thereby reducing the need for numerous RPC calls.