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

Spawning GameObject from server on specific client (who own object)

Discussion in 'Scripting' started by Gogin, Sep 25, 2018.

  1. Gogin

    Gogin

    Joined:
    Nov 9, 2013
    Posts:
    60
    Hi,

    I am trying to spawn reward (game object) from killing enemy on specific client (from server) - no need to show reward on all clients (just specific one who kill the enemy)

    I got 2 ways ideas how to proceed:

    1. spawn reward on all clients and then destroy object which is not owner
    2. send RPC to all clients and check if I am owner of GameObject, if so - spawn game object


    What do you think its best aproach to fit my requirments? any new better idea?

    Code for second option (currently error because rewardPrefab is null):

    Code (CSharp):
    1.     //Get localPlayerAuthority
    2.     public bool IsLocalPlayerOwnObject(GameObject targetObject)
    3.     {
    4.         var networkIdentity = targetObject.GetComponent<NetworkIdentity>();
    5.  
    6.         if(targetObject == null)
    7.         {
    8.             Debug.Log("Missing NetworkIdentity in GameObject: " + targetObject.name);
    9.             return false;
    10.         }
    11.  
    12.         return networkIdentity.hasAuthority; //localPlayerAuthority
    13.     }
    14.  
    Code (CSharp):
    1.    
    2. //Instantiate Graphic Reward on specific client(just in his client scene)
    3.     [ClientRpc]
    4.     public void RpcInstantiateGraphicReward(GameObject rewardPrefab, GameObject ownedObj, GameObject spawnTarget)
    5.     {
    6.         NetworkScripts nc = new NetworkScripts();
    7.  
    8.         //not defined objs
    9.         if (ownedObj == null || rewardPrefab == null || spawnTarget == null)
    10.         {
    11.             Debug.Log("Object/s is null:" + (rewardPrefab == null ? "rewardPrefab" : "") + " \n " + (ownedObj == null ? "ownedObj" : "") + " \n " + (spawnTarget == null ? "spawnTarget" : ""));
    12.             return;
    13.         }
    14.  
    15.         Debug.Log("Am I Own obj?"+ ownedObj);
    16.  
    17.         if (!nc.IsLocalPlayerOwnObject(ownedObj)) //Is player own object
    18.         {
    19.             Debug.Log("I do not own this structure, returning - no spawning reward!");
    20.             return; //I dont own this structure, return!
    21.         }
    22.  
    23.         Debug.Log("I own this structure, spawning reward on my client side.");
    24.  
    25.         //Spawn reward on client who own object which killed mob!
    26.         GameObject reward = Instantiate(rewardPrefab, spawnTarget.transform.position, spawnTarget.transform.rotation) as GameObject;
    27.  
    28.         //Move reward up
    29.         Destroy(reward, 2f); //destroy reward after 2s
    30.     }
     
  2. Nigey

    Nigey

    Joined:
    Sep 29, 2013
    Posts:
    1,129
    Those two options will send messages to all clients, which isn't optimal. You might want to consider using https://docs.unity3d.com/ScriptReference/Networking.NetworkServer.SendToClient.html and https://docs.unity3d.com/ScriptReference/Networking.NetworkClient.RegisterHandler.html. This way you can send a message to a specific client instead of all clients.

    Thinking more on it though. Supposing the enemy is one that's shared between all on the server, when the server is notified that the enemy has been killed by a client and is about to destroy the object on all clients, it can then use the above to send a message to the client who made the call using connectionId. When connectionId is missing send it as a parameter under the kill command as something player 'killedByConnectionId' or something.

    Sounds optimal-ish to me.
     
  3. Gogin

    Gogin

    Joined:
    Nov 9, 2013
    Posts:
    60
    Nigey,

    Thank you for reply. Can you please share with me some sample code?

    EDIT:

    I guess I found easy solution for this:

    https://docs.unity3d.com/ScriptReference/Networking.TargetRpcAttribute.html

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.Networking;
    3.  
    4. public class Example : NetworkBehaviour
    5. {
    6.     [TargetRpc]
    7.     public void TargetDoMagic(NetworkConnection target, int extra)
    8.     {
    9.         Debug.Log("Magic = " + (123 + extra));
    10.     }
    11.  
    12.     [Command]
    13.     void CmdTest()
    14.     {
    15.         TargetDoMagic(connectionToClient, 55);
    16.     }
    17. }
    Thanks
    Jan
     
    Last edited: Sep 25, 2018