- Home /
 
List<> and Crafting null reference.
Hello, I am having trouble with some code, whenever I click the craft wall guy button, it will throw a null reference and then not continue(instead of fully doing the craft void, and returning). I think the problem has to do with either/or/both of the scripts, the crafting function in playerinventory, or the constructors/premade recipes. Thanks. I provided the whole code below.
Script(Recipe constructor.)
 using UnityEngine;
 using System.Collections;
 using System.Collections.Generic;
 
 public static class CraftingRecipes {
 
     public static CraftingItem WoodenWall(){
        CraftingItem ct = new CraftingItem ();
        ct.InputItem.Add (ItemConstructors.Wood());
        ct.InputItem.Add (ItemConstructors.Wood());
        ct.OutputItem = ItemConstructors.WoodenWall ();
        return ct;
     }
 
     public static CraftingItem StoneWall(){
        CraftingItem ct = new CraftingItem ();
        ct.InputItem.Add (ItemConstructors.Stone());
        ct.InputItem.Add (ItemConstructors.Stone());
        ct.OutputItem = ItemConstructors.StoneWall ();
        return ct;
     }
 
     public static CraftingItem FirePit(){
        CraftingItem ct = new CraftingItem ();
        ct.InputItem.Add (ItemConstructors.Wood());
        ct.InputItem.Add (ItemConstructors.Stone());
        ct.OutputItem = ItemConstructors.FirePit ();
        return ct;
     }
 
 }
 Script(Crafting):
 
 using UnityEngine;
 using System.Collections;
 using System.Collections.Generic;
 using System.Linq;
 
 public class PlayerInventory : MonoBehaviour {
 
     public int MaxInventory = 26;
 
     public List<Item> InventoryItems = new List<Item>();
 
     void OnGUI(){
         if (GUILayout.Button ("+5 Wood")) {
             AddItem(ItemConstructors.Wood());
             AddItem(ItemConstructors.Wood());    
             AddItem(ItemConstructors.Wood());    
             AddItem(ItemConstructors.Wood());    
             AddItem(ItemConstructors.Wood());    
         }
         if (GUILayout.Button ("Craft Wall")) {
             Craft(CraftingRecipes.WoodenWall());
         }
 
     }
 
 
     public void AddItem(Item _item){
         if (InventoryItems.Count < MaxInventory) {
             InventoryItems.Add(_item);
         }
     }
 
     public void RemoveItem(Item _item){
         InventoryItems.Remove (_item);
     }
 
     public void UseItem(Item _item){
         if (_item.ItemType == "Food") {
             ConsumeItem(_item);
         }
     }
 
     public void ConsumeItem(Item _item){
         if (_item.ItemDur > 1) {
             _item.ItemDur--;    
             SaveItems();
         }
         else if(_item.ItemDur <= 1){
             RemoveItem(_item);
             SaveItems();
         }
     }
 
     public void SaveItems(){
         for (int i = 0; i<MaxInventory; i++) {
             PlayerPrefs.SetString("Itemn"+i,InventoryItems[i].ItemName);    
             PlayerPrefs.SetString("Itemt"+i,InventoryItems[i].ItemType);
             PlayerPrefs.SetInt("Itemv"+i,InventoryItems[i].ItemValue);
             PlayerPrefs.SetInt("Itemd"+i,InventoryItems[i].ItemDur);
         }
         LoadItems ();
     }
     public void LoadItems(){
         InventoryItems.Clear();
         for (int i = 0; i<MaxInventory; i++) {
             Item it = new Item();
             it.ItemName = PlayerPrefs.GetString("Itemn"+i);
             it.ItemType = PlayerPrefs.GetString("Itemt"+i);
             it.ItemValue = PlayerPrefs.GetInt("Itemv"+i);
             it.ItemDur = PlayerPrefs.GetInt("Itemd"+i);
             if(it.ItemName.Length <= 2 && it.ItemType.Length <= 2){
             }
             else{
             InventoryItems.Add(it);
             }
         }
     }
 
     public void Craft(CraftingItem Recipe){
         bool canCraft = ContainsAllItems (InventoryItems,Recipe.InputItem);
         if(canCraft){
             InventoryItems = InventoryItems.Except(Recipe.InputItem).ToList();
             InventoryItems.Add(Recipe.OutputItem);
         }
         else{
             Debug.Log("Invalid Items.");
         }
     }
 
     public static bool ContainsAllItems(List<Item> a, List<Item> b)
     {
         return !b.Except(a).Any();
     }
 
 }
 
               Code(Item Class):
 using UnityEngine;
 using System.Collections;
 
 [System.Serializable]
 public class Item
 {
     public string ItemName;
     public string ItemType;
     public int ItemValue;
     public int ItemDur;
 }
 
               Code(ItemConstructors):
 using UnityEngine;
 using System.Collections;
 
 public static class ItemConstructors
 {
 
     /*
      * 
      * Crafting resources.
      *
      */
 
 
     public static Item Wood(){
         Item it = new Item ();
         it.ItemName = "Wood";
         it.ItemType = "Crafting";
         it.ItemDur = 1;
         it.ItemValue = 1;
         return it;
     }
 
     public static Item Stone(){
         Item it = new Item ();
         it.ItemName = "Stone";
         it.ItemType = "Crafting";
         it.ItemDur = 1;
         it.ItemValue = 1;
         return it;
     }
     
     /*
      * 
      *Buildables.
      * 
      */
 
     public static Item WoodenWall(){
         Item it = new Item ();
         it.ItemName = "Wooden Wall";
         it.ItemType = "Build";
         it.ItemDur = 100;
         it.ItemValue = 1;
         return it;
     }
 
     public static Item StoneWall(){
         Item it = new Item ();
         it.ItemName = "Stone Wall";
         it.ItemType = "Build";
         it.ItemDur = 250;
         it.ItemValue = 1;
         return it;
     }
 
     public static Item FirePit(){
         Item it = new Item ();
         it.ItemName = "Fire Pit";
         it.ItemType = "Build";
         it.ItemDur = 50;
         it.ItemValue = 1;
         return it;
     }
 
     /*
      * 
      * Food/Consumables.
      * 
      */
     public static Item Apple(){
         Item it = new Item ();
         it.ItemName = "Apple";
         it.ItemType = "Food";
         it.ItemDur = 1;
         it.ItemValue = 1;
         return it;
     }
 
     public static Item Bread(){
         Item it = new Item ();
         it.ItemName = "Bread";
         it.ItemType = "Food";
         it.ItemDur = 2;
         it.ItemValue = 1;
         return it;
     }
 }
 
               Error:
NullReferenceException: Object reference not set to an instance of an object CraftingRecipes.WoodenWall () (at Assets/Scripts/Static/CraftingRecipes.cs:9) PlayerInventory.OnGUI () (at Assets/Scripts/Player/PlayerInventory.cs:21)
We would need to see the script containing the ItemConstructors such as Wood()
I updated the question with the script(s), is the Crafting recipe constructor, with the structure
 public static CraftingItem WoodenWall(){
        CraftingItem ct = new CraftingItem ();
        ct.InputItem.Add (ItemConstructors.Wood());
        ct.InputItem.Add (ItemConstructors.Wood());
        ct.OutputItem = ItemConstructors.WoodenWall ();
        return ct;
     }
 
                  Good, or should I change it to (this would be more convenient, but will it work the same)
 public static CraftingItem WoodenWall(){
        CraftingItem ct = new CraftingItem ();
        ct.InputItem[0] = ItemConstructors.Wood();
        ct.InputItem[1] = ItemConstructors.Wood();
        ct.OutputItem = ItemConstructors.WoodenWall ();
        return ct;
     }
 
 
 
                 I reworded the general question to make it a little easier to understand.
Does the constructor for CraftingItem allocate InputItem(s)?
I think the class CraftingItem isn't allocating InputItem properly. Can you post this class code? Or you can just do: ct.InputItem = new List(); before the first ct.InputItem.add call
Answer by rutter · Jan 17, 2014 at 01:27 AM
As @rhapsodyv pointed out, your CraftingItem class is not initializing the InputItem field.
Your code declares a list variable:
 //declare
 public List<Item> InputItem;
 
               This line would declare that same variable AND create the actual list:
 //declare and assign
 public List<Item> InputItem = new List<Item>();
 
               Declaration and assignment are distinct operations. Some languages are polite and give member variables a default value of 0 (which is where your null reference is coming from).
Yup it works. Now it just gives the recipes output item, without taking away the input item. I will post as new question I guess. Thank you for your help though! :)
Your answer
 
             Follow this Question
Related Questions
I'm trying to make a button that instantiates an item when you craft it 1 Answer
How do i wnn make scrolling gui like minecraft? 1 Answer
Problem at crafting 1 Answer
loop index error? JS 1 Answer
Crafting system NOT like minecraft 1 Answer