Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Question How to get a reference of a spawned by host object for a client

Discussion in 'Multiplayer' started by Zabei, Apr 25, 2023.

  1. Zabei

    Zabei

    Joined:
    Jul 20, 2021
    Posts:
    4
    I'm really new to netcode and relay stuff but i'm just hardstuck on understanding what is the best/easiest way to get a reference of an object that has been spawned by other player. I have a script that gets the NetworkObjectId of my spawnedCube but of course, that works only on the host which spawns the cube and so has the reference to it. I also can't seem to understand the concept of RPCs because i've taken the RPC part from somewhere and it does change the color for all players but earlier when i tried something similar, i just had the ClientRpc in script on my object that was changing the color for everyone just fine aswell. So why calling the ClientRpc on the object itself changes it for everyone but if i call the RPC from the player i need to use this more complicated system of calling the ClientRpc through ServerRpc?(All i could understand is that calling it that way means we call ClientRpc on all clients but i'm not sure if i got that correctly and even if i did, still, what is the difference from calling only the ClientRpc on the object itself?)

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using Unity.Netcode;
    5.  
    6. public class PlayerNetwork : NetworkBehaviour
    7. {
    8.     [SerializeField]private GameObject cubePrefab, spawnedCube;
    9.     void Update()
    10.     {
    11.         if(!IsOwner) return;
    12.      
    13.         if(Input.GetKeyDown(KeyCode.T)){
    14.             if(IsServer){
    15.                 spawnedCube = Instantiate(cubePrefab);
    16.                 spawnedCube.GetComponent<NetworkObject>().Spawn();
    17.             }
    18.         }
    19.         if(Input.GetKeyDown(KeyCode.C)){
    20.             redClientRpc(spawnedCube.GetComponent<NetworkObject>().NetworkObjectId);
    21.         }
    22.  
    23.         Vector3 moveDir = new Vector3(0,0,0);
    24.  
    25.         if(Input.GetKey(KeyCode.W)) moveDir.z += 1f;
    26.         if(Input.GetKey(KeyCode.S)) moveDir.z += -1f;
    27.         if(Input.GetKey(KeyCode.A)) moveDir.x += -1f;
    28.         if(Input.GetKey(KeyCode.D)) moveDir.x += 1f;
    29.  
    30.         float moveSpeed = 3f;
    31.         transform.position += moveDir * moveSpeed * Time.deltaTime;
    32.     }
    33.  
    34.     [ServerRpc]
    35.     private void startRedServerRpc(ulong networkObjectId){
    36.         redClientRpc(networkObjectId);
    37.     }
    38.  
    39.     [ClientRpc]
    40.     private void redClientRpc(ulong networkObjectId){
    41.         if(NetworkManager.Singleton.SpawnManager.SpawnedObjects.TryGetValue(networkObjectId, out NetworkObject networkObject)){
    42.             GameObject cube = networkObject.gameObject;
    43.             cube.GetComponent<MeshRenderer>().material.color = Color.red;
    44.         }
    45.     }
    46. }
     
  2. maxkcy

    maxkcy

    Joined:
    Oct 11, 2021
    Posts:
    62
    There are 2 ways in general to reference a network object. The right way is to use NetworkObjectTargetReference,
    Code (CSharp):
    1.  
    2. [ClientRpc]
    3.     private void GetSomeNetworkObjectAndDoSomethingClientRpc(NetworkObjectReference target)
    4.     {
    5.         if (target.TryGet(out NetworkObject networkObject))
    6.         {
    7.               // do stuff
    8.         }
    9.     }
    10.  
    and there is another way, (the bad way because I was using it by mistake)

    Code (CSharp):
    1.  
    2. [ServerRpc]
    3.     public void FindSomeNetworkObjectOnServerServerRpc(ulong networkObjectId, ServerRpcParams serverRpcParams = default)
    4.     {
    5.         if (NetworkManager.Singleton.SpawnManager.SpawnedObjects.TryGetValue(networkObjectId, out NetworkObject netObj))
    6.         {
    7.          
    8.                 // Do something
    9.             }
    10.    }
     
    malkere likes this.