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.
  2. Dismiss Notice

ClientRPCs and multiple script instances on a single object

Discussion in 'Multiplayer' started by Iron-Warrior, Apr 12, 2016.

  1. Iron-Warrior

    Iron-Warrior

    Joined:
    Nov 3, 2009
    Posts:
    836
    Hi, I've run into a problem when I have multiple instances of a script attached to a single networked object. When I call an RPC on the server script, it gets called only on one of the client scripts always (regardless of which server script called it). Here's an extremely simple test script:

    Code (csharp):
    1. using UnityEngine;
    2. using UnityEngine.Networking;
    3. using System.Collections;
    4.  
    5. public class DummyMessage : NetworkBehaviour {
    6.  
    7.     [SerializeField]
    8.     string name = "Dummy";
    9.  
    10.     [ServerCallback]
    11.     void FixedUpdate()
    12.     {
    13.         RpcMe();
    14.     }
    15.  
    16.     [ClientRpc]
    17.     void RpcMe()
    18.     {
    19.         Debug.Log(name);
    20.     }
    21. }
    If you add this script twice to the same object and give them different names (Dummy1 and Dummy2, for example), only the first added script will be called. If you remove the first script and run it again, the second one will be called. If this is intended, I'm assuming that ClientRPCs do not contain any information regarding which script actually called the RPC, but instead will simply call the method on the first script that was added.

    I'm using 5.2.2f1 right now since I had some problems when I upgraded my project to 5.3, but I wasn't able to find anything in the release notes for 5.3 addressing this. I also didn't see anything in the documentation about this, so I'm not sure if it's a bug or not.

    In case you were wondering why I'm trying to do this, each script instance inherits from a base class that handles things like client-side prediction and interpolation, and the player has a few different scripts that need to be interpolated (movement, weapon attacking) that are in different scripts.

    Thanks,
    Erik
     
  2. Oshroth

    Oshroth

    Joined:
    Apr 28, 2014
    Posts:
    99
    Unity does not track individual components for RPCs. When you build script with an RPC function in it, Unity modifies the script to handle the network behind the scenes, which consists of rewriting calls to [SyncVar]s, [Command]s, [ClientRPC]s, etc.
    In the case of RPCs, it assigns a unique hash to the RPC function and registers it in a dictionary with the class type and rewrites calls so they call a CallRPC function which handles creating the network packet that gets sent to the clients with the RPC hash. When you receive the packet on the client, it sends the hash to the NetworkIdentity on the object which looks in the dictionary for the hash's class type, once/if it finds it, it looks for the first component on the object that is that class or subclass and calls the matching InvokeRPC function for that hash.
     
    Iron-Warrior likes this.
  3. Iron-Warrior

    Iron-Warrior

    Joined:
    Nov 3, 2009
    Posts:
    836
    That is more or less what I suspected, but thanks for the in-depth response. It's definitely possible for me to rewrite my framework a bit to deal with this, but I wanted to be absolutely sure it was not a bug.

    I suppose if the devs wanted to they could add an extra parameter (something as simple as a short or byte) to specify the index of a component instance to allow for this, but I don't think it would have been a huge bother for me to design around it if I'd known ahead of time.