Buffered RPCs from Network.Instantiate() not removed on Network.Destroy()?

So, I am using Network.Instantiate() and Network.Destroy() to create/destroy objects with my multiplayer game.

If the server calls Network.Instantiate() and then a client connects later on, that object will be created on the client as expected. This is great.

However... If the server creates the object with Network.Instantiate() and then destroys that object with Network.Destroy() and then the client connects, that object will still be created on the client! This is very bad!

From my understanding, what is causing this problem is that the buffered RPCs created with Network.Instantiate() are not removed with Network.Destroy(). Is this is a bug or intended functionality?

The only solution I can think of is to create a unique RPC Group for every object that is Network.Instantiated and then calling Network.RemoveRPCsInGroup() for that unique RPC Group in that object's OnDisable()... if(networkView.isMine)

However, this will not work because of the (undocumented?) limit of 32 RPC groups. My game will certainly have more than 32 objects created over the course of a round.

My desired functionality is for Network.Destroy() to remove the buffered RPCs that were created with the corresponding Network.Instantiate()

This seems very reasonable...

A practical example problem:

ServerA starts a game.

ClientA connects.

The ServerA player and ClientA player start shooting at each other. 500 bullets are created with Network.Instantiate. Of those, only 3 are currently still flying (the rest have been destroyed with Network.Destroy().

ClientB connects. All 500 bullets are immediately created on ClientB's screen (instead of just the desired 3).

I am working on example project to demo this now.

Sadly, if there is no solution to this I don't think I can continue with Unity development as this is a critical issue :(

Hi,

I think this is intended to work like this, even it makes no real sense IMHO.

A possible workaround for this problem is to skip Network.Instantiate completely and write your own RPC functions to create your objects when a new client connects.

You'll have to find a way to keep track of your created objects, though.

Sorry that I have no code snippet for you at the moment, I canceled Unity networking a while ago and I don't remember that stuff correctly.

There have been other Unity geeks doing it that way, I'm sure one of them will chime in ...

-- oxl

I'm having similar problems I think and while looking around I found this answer supplied by Seon on this page

Bottom line is....

Network.Instantiate is buffered... but Network.Destroy isnt,

So re-connecting players, or newly connecting players get the buffered call to instantiate the object, but never get the call to destroy it again.

What you need to do is..

networkView.RCP("killObject", RPCMode.AllBuffered);

@RPC
function killObject() {
     Destroy(object you want destroyed);
}

Now the destroy gets called via a buffered RPC, so when people connect after the item is destroyed, there is a killObject call waiting for them to kill it off.

yes, it seems like a pain, but once you get used to coding this way and thinking this way, it's a piece of cake :-) Lemon Sponge cake :-)

Cheers :-)

This hasn't fixed my problem but it may help with yours :)

Hi,

I have the same problem. I think it's because Network.Instantiate is buffered and Network.Destroy is not.

I've solved it this way (sort of). It's not a universal/perfect solution but it works for me:

/*
All RPC function gets called before Start() 
Call Network.Destroy inside a RCP call which also gets buffered.

Instatiate the gameObject with Network.Instatiate() as normal. 
But be sure to remove the gameObject by calling: networkView.RPC ("RPCDestroy", RPCMode.AllBuffered);
*/

protected var started = false;

function Start() {
    started = true;
}

...

@RPC
function RPCDestroy () {
    if ( !started ) { /* old object - remove it */
        Destroy( gameObject );
        return;
    }

    /* Your other (normal) destroy logic here */

    if ( networkView.isMine ) {
        Network.Destroy(gameObject);
    }
}

ran into the same problem a while ago, i think i grouped the buffed stuff in group for each player, and you can unbuffer a group,group bufferd stuff in groups by player, you can unBuffer things by group

You need to cleanup the RPC’s for the object being destroyed using:

Network.RemoveRPCs(player, 0);

The Destroy doesn’t automatically do it because there could be situations where you want to keep some. In that case you might create ones to keep on channel 1 and ones to delete on channel 0, then on the player destroy (perhaps OnPlayerDisconnected for example) you’d do: (note: this runs on the server)

void OnPlayerDisconnected (NetworkPlayer player) 
{
	// Removing player if Network is disconnected
	Debug.Log("Server destroying player");
	Network.RemoveRPCs(player, 0); // remove any pending Buffered RPC's left from the disconnected player
	Network.DestroyPlayerObjects(player); // send a request to all the remaining clients to have them remove the disconnected player
}