- Home /
List with every player on the Server
When someone leaves the server, the players array still wants to access his player gameobject. Is there a way to create the playerlist without the players array?
void Start() {
playerlist = new List<Transform>();
players = GameObject.FindGameObjectsWithTag("Player");
foreach(GameObject p in players) {
playerlist.Add(p.transform);
}
}
void OnPlayerConnected() {
playerlist.Clear();
players = GameObject.FindGameObjectsWithTag("Player");
foreach(GameObject p in players) {
playerlist.Add(p.transform);
}
}
void OnPlayerDisconnected(NetworkPlayer player) {
playerlist.Clear();
players = GameObject.FindGameObjectsWithTag("Player");
foreach(GameObject p in players) {
playerlist.Add(p.transform);
}
}
Answer by Dave-Carlile · Nov 02, 2013 at 03:36 PM
Shouldn't OnPlayerDisconnected
remove the player? All you're doing is finding all the objects tagged "Player" and adding them to the list. You need to actually find the player object that represents the disconnected player and remove that object.
I do something like this, using the NetworkPlayer.guid property as part of the player object name so I can identify it easily...
void OnPlayerDisconnected(NetworkPlayer player)
{
Transform playerTransform = GameObject.Find("Player_" + player.guid);
if (playerTransform != null)
Destroy(playerTransform.gameObject);
Network.RemoveRPCs(networkPlayer);
Network.DestroyPlayerObjects(networkPlayer);
}
When adding the player you need to make sure you set the name to "Player_" + player.guid. I do this in OnPlayerConnected
.
I also add all the player objects to a parent game object so the Find
only has to search through a short list. This still isn't the most efficient - using a Dictionary
or somethign would be faster still. The basic idea though is that in OnPlayerDisconnect
you need to be able to identify the specific player object that disconnected and remove it.
The player gets removed in another script since this is part of the monster ai script.
void OnPlayerDisconnected(NetworkPlayer p)
{
Network.RemoveRPCs(p);
Network.DestroyPlayerObjects(p);
}
Then either this script is running before the one that calls DestroyPlayerObjects, or DestroyPlayerObjects isn't destroying your player object. Note that DestroyPlayerObjects only destroys objects based on the view ID
, so if your player game object doesn't have a NetworkView
on it it won't be destroyed.
I tried this code:
void OnPlayerDisconnected(NetworkPlayer player) {
Network.RemoveRPCs(player);
Network.DestroyPlayerObjects(player);
playerlist.Clear();
players = GameObject.FindGameObjectsWithTag("Player");
foreach(GameObject p in players) {
playerlist.Add(p.transform);
}
}
But it still gives me the error every update. Edit: The gameobject is instatiated by the client and gets deleted. The problem is that something (I think the players array) is trying to access the deleted gameobject. Error:
$$anonymous$$issingReferenceException: The object of type 'Transform' has been destroyed but you are still trying to access it.
Your script should either check if it is null or you should not destroy the object.
UnityEngine.Transform.get_position () (at C:/BuildAgent/work/ea95e74f6e5f192d/Runtime/ExportGenerated/Editor/UnityEngineTransform.cs:26)
$$anonymous$$onsterScript.<SortPlayersByDistance>m__0 (UnityEngine.Transform p1, UnityEngine.Transform p2) (at Assets/Scripts/$$anonymous$$onsterScript.cs:77)
System.Array.qsort[Transform] (UnityEngine.Transform[] array, Int32 low0, Int32 high0, System.Comparison`1 comparison) (at /Applications/buildAgent/work/c514da0c8183631c/mcs/class/corlib/System/Array.cs:1774)
System.Array.Sort[Transform] (UnityEngine.Transform[] array, Int32 length, System.Comparison`1 comparison) (at /Applications/buildAgent/work/c514da0c8183631c/mcs/class/corlib/System/Array.cs:1699)
Rethrow as InvalidOperationException: Comparison threw an exception.
Edit 2: When I move the code into the Update script, it works, but gives me a warning(?)
No objects for the given player ID were deleted 1
which is weird because the player gets deleted