OK, I know that Network.Instantiate() works using buffered RPC calls; does anyone have a recommended system for getting rid of those buffered calls after they're no longer needed?
The issue, as I'm sure many of you have come across, is that those buffered RPCs can stack up after they're useful. The symptom that brought this to our attention is that, because Network.Destroy() doesn't use buffered RPC calls, new clients get the calls to Instantiate already-destroyed objects and don't get corresponding messages to destroy them. This results in ghost copies of whatever it is you instantiate and destroy.
Now, one solution would be to add a buffered RPC call that destroys the objects. Which would work, but the RPC buffer could get really bloated with unnecessary calls, and we'd need to be careful about initialization--we wouldn't really want clients to load models, animations, etc. for things that don't really exist anymore.
So we're thinking we'd like to use Network.RemoveRPCsInGroup() to get rid of the RPCs (reserving a bunch of communication groups to be claimed by each Network.Instantiate() call). Has anyone tried this, who can share their experiences/pitfalls encountered? The other option I can think of would be to make explicit all of the RPC calls included in Network.Instantiate(), which seems less ideal...
Didn't they fix this in 3.2? What's new in Unity 3.2
Networking: It's now possible to remove Network.Instantiate calls from the RPC buffer by calling Network.RemoveRPCs on the first NetworkView in the instantiated object.
So, right before you destroy your Network.Instantiated object, I imagine you do something like:
Network.RemoveRPCs(objectImDestroying.GetComponent(NetworkView));
(I think. If the object has multiple networkViews you might need to use GetComponents and call RemoveRPCs on the first entry in the array it returns).
You would use RemoveRPCS and give it the Netowork.player that you want to remove the buffered stuff for. So if you know you used Network.Instantiate() or your own instantiate from a specific client that disconnected all you need to do is call RemoveRPCS(Network.player) for which ever network player disconnected and you shouldn't see their buffered RPCs anymore.
This works for me.
In code it would look like this.
function OnPlayerDisconnected(player: NetworkPlayer) {
//Destroy all the objects currently in the scene created by this player and remove his info from the list
Network.RemoveRPCs(player);
Network.DestroyPlayerObjects(player);
}
This should do the trick.
Hi
I am a bit new to programming, so can you show or explain how to add the Buffered Network.Destroy RPC Call?
Really need this.
Thanks.
I’d like to add a note to this thread.
I just spent the whole day struggling with this issue (sidetracked by this issue, rather), because the RemoveRPCs call didn’t appear to be working correctly.
What I instead discovered was that when I call an RPC on the SERVER and perform Network.Instantiate, it actually ends up creating a separate instance of a network-instantiated object FROM EACH CONNECTED PLAYER. (I confirmed that there were multiple instances of the same object being instantiated right on top of each other, all with their own unique viewIDs belonging to each player; I confirmed it with their Network.Player as well)
I don’t know if this is a bug or intended behavior (I don’t see why it should behave this way, TBH), but due to this I was not able to remove the RPC(s) correctly from the buffer for the longest time.
In the end, what I did was:
- Instead of Network.Instantiating the object from within an RPC on the server,
- I called Network.Instantiate directly from the server
That did the trick for me. No more duplicate copies of the object, and RemoveRPCs started behaving “correctly” as well.
I guess the point I’m trying to make is, if you are having ghost objects even after RemoveRPC-ing, check to see how many instances are actually spawned before you try Network.Destroy or RemoveRPC. If you have multiple copies, you could be having similar issues of RPC-induced server-side Network.Instantiations actually instantiating on the Client(s) side.
If I’m not making sense, I apologize. I literally spent 8 hours cutting this issue from every angle and am not sure if I’m even thinking straight anymore. ;D-
Like PrimeDerektive says in the “accepted” answer, you should use Network.RemoveRPCs. One subtlety that isn’t clear is that the RPCs are buffered on the server, even if you call Network.Instantiate on one of the clients. This means that you should use a method like this:
[RPC]
void RemoveBufferedInstantiate (NetworkViewID viewID) {
if (Network.isServer) {
Network.RemoveRPCs (viewID);
} else {
networkView.RPC ("RemoveBufferedInstantiate", RPCMode.Server, viewID);
}
}
With this code, you can call RemoveBufferedInstantiate (networkView.viewID); without having to consider if you’re on the server or the client.
Your code would then look like:
RemoveBufferedInstantiate (someObject.networkView.viewID);
Network.Destroy (someObject);
I’ve written this method to solve the issue
* }*
* }*