- 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