Cant load variable of other script from constructor
The thing is, I have a class GameItemContainer which has a static variable Container which is used to store the values imported from an XML file. I have another class named Item in which if I try to get the value of GameItemContainer.Container.items from the class variable's get command everything works fine, but if I call it from the constructor, it returns null for GameItemContainer.Container.
Here is Item.cs:
using UnityEngine;
using System.Collections.Generic;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
public class Item
{
public string Name {get;set;}
public string Price {get;set;}
[XmlArray("ItemsNeededNames"), XmlArrayItem("ItemName")]
public List<string> ItemsNeededNames { get; set; }
public List<Item> ItemsNeeded {
get {
List<Item> allItems = GameItemContainer.Container.items; // All good
List<Item> _neededItems = new List<Item> ();
for (int i = 0; i < ItemsNeededNames.Count; i++) {
for (int j = 0; j < allItems.Count; j++) {
if (ItemsNeededNames [i].ToLower () == allItems [j].Name.ToLower ()) {
_neededItems.Add (allItems [j]);
break;
}
}
}
return _neededItems;
}
}
//Constructors
public Item() {}
public Item(string itemName)
{
Debug.Log (GameItemContainer.Container); // it prints null
var allItems = GameItemContainer.Container.items; // NullReferenceException
for (int i = 0; i < allItems.Count; i++) {
if (allItems[i].Name.ToLower() == itemName.ToLower()) {
this.Name = allItems[i].Name;
this.Price = allItems[i].Price;
this.ItemsNeededNames = allItems[i].ItemsNeededNames;
break;
}
}
}
}
Notice that inside ItemsNeeded I have:
List<Item> allItems = GameItemContainer.Container.items;
And if I do
print(GameItemContainer.Container.items[0].ItemsNeeded[0].Name);
from another script it prints what it needs to print, but calling that same thing from the constructor gives me null.
And here is GameItemContainer.cs:
using UnityEngine;
using System.Collections.Generic;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
[XmlRoot("GameItemCollection")]
public class GameItemContainer
{
[XmlArray("Items"),XmlArrayItem("Item")]
public List<Item> items = new List<Item> ();
// The problem comes when initializing items like this
public static Item lighter = new Item("lighter");
public static GameItemContainer Container = LoadXML ("gameItems");
private static GameItemContainer LoadXML(string xmlname) {
return GameItemContainer.Load (Path.Combine (Application.dataPath, "Scripts/XML/" + xmlname + ".xml"));
}
public static GameItemContainer Load(string path)
{
XmlSerializer serializer = new XmlSerializer(typeof(GameItemContainer));
using(var stream = new FileStream(path, FileMode.Open))
{
return serializer.Deserialize(stream) as GameItemContainer;
}
}
}
It throws the error NullReferenceException: Object reference not set to an instance of an object at line inside the Item constructor
var allItems = GameItemContainer.Container.items; // NullReferenceException
I think there aren't any errors and I've been struggling with this the past few hours. Any help would be greatly appreciated.
Answer by garmekain · Mar 18, 2016 at 03:40 PM
I found the error. What I needed to do is change
public static GameItemContainer Container = LoadXML("gameItems");
To
public static GameItemContainer Container { get { return LoadXML("gameItems "); } }
But this creates another question. Isnt it going to be much less efficient because it has to load the file each time GameItemContainer.Container is used? Any tips to avoid that?