KeyNotFoundException: The given key was not present in the dictionary. (UNET)

Hello everyone,

I’ve gotten into game development and unity about 6 months ago, started developing for vr pretty fast. I’ve been following a tutorial for a multiplayer fps which I’ve been iterating and continuing further development on. Before I started translating to vr everything worked perfectly. I’ve also not changed anything about the networking components I am using so coming across this error doesn’t really make sense to me. So here it is:

Error:

KeyNotFoundException: The given key was not present in the dictionary.
System.Collections.Generic.Dictionary`2[System.String,Player].get_Item (System.String key) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Collections.Generic/Dictionary.cs:150)
GameManager.GetPlayer (System.String _playerID) (at Assets/Scripts/GameManager.cs:44)
PlayerShoot.CmdPlayerShot (System.String _playerID, Int32 _damage, System.String _shootSourceID) (at Assets/Scripts/PlayerShoot.cs:222)
PlayerShoot.InvokeCmdCmdPlayerShot (UnityEngine.Networking.NetworkBehaviour obj, UnityEngine.Networking.NetworkReader reader)
UnityEngine.Networking.NetworkIdentity.HandleCommand (Int32 cmdHash, UnityEngine.Networking.NetworkReader reader) (at C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkIdentity.cs:620)
UnityEngine.Networking.NetworkServer.OnCommandMessage (UnityEngine.Networking.NetworkMessage netMsg) (at C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkServer.cs:1297)
UnityEngine.Networking.NetworkConnection.HandleReader (UnityEngine.Networking.NetworkReader reader, Int32 receivedSize, Int32 channelId) (at C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkConnection.cs:453)
UnityEngine.Networking.NetworkConnection.HandleBytes (System.Byte buffer, Int32 receivedSize, Int32 channelId) (at C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkConnection.cs:409)
UnityEngine.Networking.NetworkConnection.TransportRecieve (System.Byte bytes, Int32 numBytes, Int32 channelId) (at C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkConnection.cs:561)
UnityEngine.Networking.NetworkServer.OnData (UnityEngine.Networking.NetworkConnection conn, Int32 receivedSize, Int32 channelId) (at C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkServer.cs:753)
UnityEngine.Networking.NetworkServer+ServerSimpleWrapper.OnData (UnityEngine.Networking.NetworkConnection conn, Int32 receivedSize, Int32 channelId) (at C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkServer.cs:1845)
UnityEngine.Networking.NetworkServerSimple.HandleData (Int32 connectionId, Int32 channelId, Int32 receivedSize, Byte error) (at C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkServerSimple.cs:382)
UnityEngine.Networking.NetworkServerSimple.Update () (at C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkServerSimple.cs:248)
UnityEngine.Networking.NetworkServer.InternalUpdate () (at C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkServer.cs:705)
UnityEngine.Networking.NetworkServer.Update () (at C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkServer.cs:655)
UnityEngine.Networking.NetworkIdentity.UNetStaticUpdate () (at C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkIdentity.cs:1060)

Code:

This error happens at this part of the code:

[Client]
	void ShootR ()
	{
		
		if (!isLocalPlayer)
		{
			Debug.Log ("is not local player");
			return;

		}
		Debug.Log ("is local player");

		//We are shooting right, call the Onshoot method on the server
		CmdOnShootR ();


		RaycastHit _hit;

		//check if hit something
		if (Physics.Raycast(firepointR.transform.position, firepointR.transform.forward, out _hit, currentWeaponR.range) )
		{	Debug.Log ("checked hit");
			// we hit something
			if (_hit.collider.tag == PLAYER_TAG)
			{ 	Debug.Log ("hit player");
				CmdPlayerShot (_hit.collider.name, currentWeaponR.damage, transform.name); //error happens here
				Debug.Log ("We hit" + _hit.collider.name);
			}

			// we hit something, call the onhit method on the server
			CmdOnHitR (_hit.point, _hit.normal);
		}
	} // calls for this function:
[Command]
void CmdPlayerShot (string _playerID, int _damage, string _shootSourceID)
{
	Debug.Log (_playerID + " has been shot.");
	Player _player = GameManager.GetPlayer (_playerID);
	_player.RpcTakeDamage (_damage, _shootSourceID);
}

This is my Gamemanager script that takes care of the dictionary:

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

public class GameManager : MonoBehaviour {

	public static GameManager instance;

	public MatchSettings matchSettings;

	[SerializeField]
	private GameObject sceneCamera;

	void Awake(){
		if (instance != null)
		{
			Debug.LogError ("More than one GameManager in scene.");
		} else {
		instance = this;
		}
	}

	#region Player tracking

	private const string PLAYER_ID_PREFIX = "player ";

	private static Dictionary<string, Player> players = new Dictionary<string, Player> ();

	public static void RegisterPlayer (string _netID, Player _player)
	{
		string _playerID = PLAYER_ID_PREFIX + _netID;
		players.Add (_playerID, _player);
		_player.transform.name = _playerID;
	}		

	public static void DeRegisterPlayer (string _playerID)
	{
		players.Remove (_playerID);
	}

	public static Player GetPlayer (string _playerID)
	{
		return players [_playerID];
	}

	public static Player[] GetallPlayers()
	{
		return players.Values.ToArray ();
	}

	#endregion
	public void SetSceneCameraActive(bool isActive)
	{
		if (sceneCamera == null)
		{
			return;
		} else
		{
			sceneCamera.SetActive (isActive);
		}

	}
}

I really hope someone can help me. Spend about 8 hours today trying to figure this out as I had to hire a room and an extra VR headset, this is of course a big bummer.
A million thanks!

Also, really new to forums like this, so if I’m doing something wrong in my way of posting let me know

public static Player GetPlayer (string _playerID)
{
return players [_playerID];
}

This “” is an index into the dictionary, but you are NOT checking that this index is in-fact valid, before using it, thus the error is generated when an _playerID, that in NOT already in the dictionary is indexed. Note: only keys that have been added to the dictionary previously can be a “valid” index. (so , in your posted code, you are not calling RegisterPlayer() on the playerID, first.)

I suggest you check it exists in the Dictionary first:

public static Player GetPlayer (string _playerID)
     {
         if(!player.Contains(_playerID))
            { debug.Log("hey! this played id is no good! " + playerID); return;}
         return players [_playerID];
     }