- Home /
List.Where does not return
Ok, I made a few scipts and in one of them I got a function that searches a list and returns the values.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
public class ItemDictionary : MonoBehaviour
{
public List<ItemListTemplate> ItemList = new List<ItemListTemplate> ();
public Material MedkitMat;
public Material SyringeMat;
public Material AntidoteMat;
void Start ()
{
RegisterItems ();
}
void RegisterItems ()
{
ItemList.Add (new ItemListTemplate (0, null, "", "", "", false, false, 0, new int[] { 0 }));
ItemList.Add (new ItemListTemplate (1, MedkitMat, "Medkit", "A medkit. Maybe can be used for healing?", "consumable", true, false, 1, new int[] { 25 }));
ItemList.Add (new ItemListTemplate (2, SyringeMat, "Syringe", "Just an empty syringe.", "material", false, false, 0, new int[] { 0 }));
ItemList.Add (new ItemListTemplate (3, AntidoteMat, "Antidote", "Heals you a lot. Suspiciously easily crafted just by placing a medkit into a syringe...", "consumable", true, false, 1, new int[] { 50 }));
}
public ItemListTemplate LookForItem(int itemid){
return ItemList.Where (x => x.ItemID == itemid).SingleOrDefault ();
}
}
public class ItemListTemplate
{
public int ItemID;
public string ItemName;
public Material ItemMaterial;
public string Description;
public string Category;
public bool Usable;
public bool Equipable;
public int Action;
public int[] ActionParams;
public ItemListTemplate (int id, Material mat, string name, string desc, string cat, bool useabl, bool equip, int act, int[] actparams)
{
ItemID = id;
ItemName = name;
Description = desc;
Category = cat;
Usable = useabl;
Equipable = equip;
Action = act;
ActionParams = actparams;
ItemMaterial = mat;
}
public int GetID ()
{
return ItemID;
}
public string GetName ()
{
return ItemName;
}
public string GetDesc ()
{
return Description;
}
public string GetCategory ()
{
return Category;
}
public bool GetUsable ()
{
return Usable;
}
public bool GetEquipable ()
{
return Equipable;
}
public int GetAction ()
{
return Action;
}
public int[] GetActionParams ()
{
return ActionParams;
}
public Material GetMaterial(){
return ItemMaterial;
}
}
Then, for example I get the values back with
Texture2D texture = (Texture2D)dict.LookForItem(id).GetMaterial().mainTexture;
where id is the ID of the item and dict is the ItemDictionary script. This works well, but for some reason, when I try to run this code from other script, it does not.
using UnityEngine;
using System.Collections;
using System.Linq;
public class PickableDefinition : MonoBehaviour {
public int ItemID;
public bool pickable;
ItemDictionary dict;
void Start(){
dict = GameObject.Find ("GameController").GetComponent<ItemDictionary> ();
if (pickable) {
this.tag = "Pickable";
}
reloadSprite ();
}
public void reloadSprite (){
GetComponent<Renderer> ().material = dict.LookForItem (ItemID).GetMaterial ();
}
}
This is the code from PickableDefinition script and the function reloadSprite returns null and NullReferenceException: Object reference not set to an instance of an object. I got all the values required set-up.
I also have cut out other parts of the scripts, so they don't disturb you but they have nothing to do with this.
Thanks
Perhaps dict = GameObject.Find ("GameController").GetComponent<ItemDictionary> ();
is null..
It is not. I tried to print out the value of GameObject.Find ("GameController").GetComponent () and it says ItemDictionary, not null.
$$anonymous$$aybe you don't have a Renderer attached and GetComponent<Renderer>().material
throws the NullReferenceException?
Answer by Bunny83 · Apr 09, 2018 at 03:48 AM
Well, if you ruled out all the cases the others have mentioned your desired item simply wasn't found in your dictionary. You use FirstOrDefault. So if the linq extension "Where" doesn't find any match it returns the default value for the element type. Since your element type is a class the default value is null.
Unless you are 100% sure that a certain element / item is present you should always do a null check in such cases:
var item = dict.LookForItem (ItemID);
if (item != null)
{
GetComponent<Renderer> ().material = item.GetMaterial ();
}
else
Debug.LogWarning("No item in dictionary with id: "+ ItemID);
Note that you call "RegisterItems" in Start of your "ItemDictionary" class. Are you sure that you don't try to find an item before they are "registrated"?
Try printing the count of your "ItemList".
Debug,Log("Number of items in dictionary: " + dict.ItemList.Count);
Thank you very much.
I was trying to search the list before I have added stuff into it.