Reading the documentation, it's not clear to me which object references I should be able to pass around in commands. Can I pass any part (the gameobject itself, component) of a spawned object in a command? Do the have to be NetworkBehaviours? Code (CSharp): [Command] void CmdDoSomething(GameObject obj) { // do something } [Command] void CmdDoSomething2(MyScriptAttachedToASpawnedObject obj) { // do something } I'm experiencing some problems with it and I don't understand if I'm just doing something that is not supported or if there's another problem. For example I was able to pass a NetworkIdentity reference of a runtime-spawned object but the same thing doesn't seem to work for a scene object (null reference exception on server) Code (CSharp): // this works for a runtime-spawned object but not if obj is the identity of a scene object [Command] void CmdDoSomething(NetworkIdentity obj) { // do something }
You cannot pass a component of a GameObject. You can pass a GameObject with a NetworkIdentity, a NetworkIdentity itself or a NetworkInstanceId. It shouldn't make a difference if the object is in the scene or spawned, both can be looked up on the server by NetworkInstanceId using NetworkServer.FindLocalObject.
It doesn't work in commands for me, sending a reference to a (dedicated) server. The same thing works when connected to a server that is a host. By looking into ReadGameObject function of NetworkReader, it looks like it always tries to find the object in the ClientScene, not NetworkServer. Code (CSharp): public GameObject ReadGameObject () { NetworkInstanceId networkInstanceId = this.ReadNetworkId (); if (networkInstanceId.IsEmpty ()) { return null; } GameObject gameObject = ClientScene.FindLocalObject (networkInstanceId); if (gameObject == null && LogFilter.logDebug) { Debug.Log (string.Concat (new object[] { "ReadGameObject netId:", networkInstanceId, "go:", gameObject })); } return gameObject; } This bug was already in the issue tracker and is marked as fixed there: http://issuetracker.unity3d.com/issues/networkreader-dot-readnetworkidentity-assumes-it-is-on-client Is this fix not yet in 5.1.1 ?
For those who have the same issue, here's a workaround that works for commands in 5.1.1. Just pass the NetworkInstanceId instead of the object itself. Code (CSharp): //instead of CmdDoSomething(someObject); CmdDoSomething [Command] public void CmdDoSomething(GameObject obj) { //do something with obj } // send only the id CmdDoSomethingWorkaround(someObject.GetComponent<NetworkIdentity>().netId); [Command] public void CmdDoSomethingWorkaround(NetworkInstanceId objId) { GameObject obj; if (Game.networkManager.isClient) obj = ClientScene.FindLocalObject (objId); else obj = NetworkServer.FindLocalObject (objId); //do something with obj }
Hello! Anyone know is it optimized to pass GameObject as parametr to Commad/Rpc? I mean, I can pass like int id or string name and then find object by this value. Does it need significantly more bandwidth to pass GameObject or it uses kinda same algorithm (pass ID and then find it on other side)?
Assuming I'm right, if you were to send a GameObject as a parameter all they would do is send a reference/pointer to the object. And due to the way RAM works, I'd think a pointer on computer could point to completely different memory because you can have one person with 8GBs and another with 32GBs. Send the netID. And then find it on the server or other clients by using NetworkServer.FindLocalObject().
As they said above, if you pass a gameobject with a NetworkIdentity to a Cmd or Rpc, it will send its netid and the server/clients on the other side will use FindLocalObject() to get the gameobject. Netid is guaranteed to be unique to an object and matches all network versions of that object. A pointer is completely useless outside of the computer that it is associated with, even if the computers had the same amount of ram, the program is running in a completely different address space.