How do you remove RPC's from the RPC buffer that where created on behalf of a player that is now disconnected with an authoritative server?

I struggled with this for days and now have a solution. Here is the setup…You have a client who wants to create an object in your game world but you want your server to be authoritative. So the client sends an RPC to the server asking the server to create an object on his/her behalf. Another client connects, your server sends the new client all of the info about the objects that have been added to the world by other players.

Now, a client disconnects. You want your server to remove all of the disconnected players objects from everyone who is currently connected’s game world and prevent any future players from creating objects that should no longer exists in the game world. How do you do this…I will post my solution and see what y’all think.

Here is what I did. I had the client send the server an RPC requesting the server to make the object. The big problem is how do you get the server to remove the RPC that he sends to the clients from the buffer after the player that made the request disconnects? Well you can use the RemoveRPCs() function that accepts a viewID…the problem is you have to give it the viewID that the object was created with so if you try to assigne it a viewID from the players pool and call RemoveRPCs() with the players viewID it wont work. The server is the one that created the object with Network.Instantiate() and its original viewID will be one from the servers pool of viewID’s .
Quick FYI: Network.Instantiate’s are automatically put on the RPC buffer and Network.Destroy()'s are not buffered…so that is not fun :frowning:
You have to come up with a system of keeping track of what player request the server to Network.Instantiate what item.

I used a list (see the networkObjects list in the code) to store

-What player requested the item be made
-What the viewID the server originally assigned to the object

With those two things you can get the job done. I dont have time to do a full write up/tutorial but i will post my code to show you how I got it done…good luck :slight_smile:

The main script NetworkingScript: (The thingToInstanciate that i have as “test”…it does nothing so dont let that trip you up)

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class NetworkScript : MonoBehaviour {
	
	public GameObject PlayerPrefab;
	public Transform cubePrefab;

	List<networkObjectsClass> networkObjects = new List<networkObjectsClass>();
	
	void OnServerInitialized(){
		Debug.Log("The Server has been INITALIZED!");
		Network.Instantiate(PlayerPrefab, GameObject.Find("PlayerSpawn").transform.position, Quaternion.identity, 0);
	}
	
	void OnConnectedToServer(){
		if(Network.isClient){
			Network.Instantiate(PlayerPrefab, GameObject.Find("PlayerSpawn").transform.position, Quaternion.identity, 0);
		}
	}
	
	void OnPlayerDisconnected(NetworkPlayer player) {
        Debug.Log("Clean up after player " + player);
		//This will find the viewID's associated with the disconnected player
		for(int i = 0; i < networkObjects.Count; i++) {
			if(networkObjects*.Player == player.ToString()){*

_ Debug.Log ("Removing "+networkObjects*.viewID);_
_ Network.RemoveRPCs(networkObjects.viewID);
Network.Destroy(networkObjects.viewID);
}
}
Debug.Log("Size of the list "+networkObjects.Count);
//Keeps the networkObjects list from having old info in it*

* networkObjects.RemoveAll(tempList => tempList.Player == player.ToString());
Debug.Log("New size "+networkObjects.Count);
//Dont think this is removing any RPC’s because no*

* //player RPC should be buffered but just in case*
Network.RemoveRPCs(player);
* //Delets the player’s Character*
* Network.DestroyPlayerObjects(player);
}*_

* void OnGUI(){*
* if(!Network.isServer && !Network.isClient){*
* if(GUI.Button(new Rect(10,10,Screen.width/8,Screen.height/16), “Start Server”)){*
* Network.InitializeServer(32, 1337, false);*
* }*
* else if(GUI.Button(new Rect(10, 35, Screen.width/8, Screen.height/16), “Connect”)){*
* Network.Connect(“127.0.0.1”, 1337);*
* }*
* }*
* if(Network.isClient){*
* if (GUILayout.Button(“SpawnBox”)) {*
* networkView.RPC(“SpawnBox”, RPCMode.Server, Network.player, “test”, GameObject.FindGameObjectWithTag(“Player”).transform.position);*
* } *
* }*
* //Server directly calls the InstanciateToNetwork function*
* else if(Network.isServer){*
* if (GUILayout.Button(“SvrSpawnBox”)) {*
* InstanciateToNetwork(Network.player, “test”, GameObject.FindGameObjectWithTag(“Player”).transform.position);*
* } *
* }*
* }*
* void InstanciateToNetwork(NetworkPlayer player, string thingToInstanciate, Vector3 location){*
* Transform clone;*
* clone = Network.Instantiate(cubePrefab, location, Quaternion.identity, 0) as Transform;*
//Makes sure that the player is not the server
* if(player.ToString() != “0”){*

* NetworkView nView;*
* nView = clone.GetComponent();*

* //Keep track of the original viewID so that it can be removed from the RPC buffer*
* networkObjects.Add(new networkObjectsClass(player.ToString(), nView.viewID));*

* //This is just for debuging*
* for(int i = 0; i < networkObjects.Count; i++){*
Debug.Log("Player: “+networkObjects_.Player+” Original ViewID "+networkObjects*.viewID);
}
}
}
[RPC]
void SpawnBox(NetworkPlayer player, string thingToInstanciate, Vector3 location) {
if(Network.isServer){
InstanciateToNetwork(player, thingToInstanciate, location);
}
}
}*

The supporting script networkingObjectsClass:
using UnityEngine;
using System.Collections;_

public class networkObjectsClass : MonoBehaviour{
* private string _player;*
private NetworkViewID _viewID;

public string Player { get{ return _player;} set{ _player = value;}}
public NetworkViewID viewID { get{ return _viewID;} set{ _viewID= value;}}

public networkObjectsClass(string player, NetworkViewID viewID){
* player = player;
viewID = viewID;*
}

}