- Home /
Variables in components always returning null?
Im trying to access data from another gameobject, I'm in the position to use a reference via the inspector, but for some reason everytime I try to access the list created in the other class its ALWAYS null. I don't get it.
Here's the relevant pseudo-code:
public class DStarMap : MonoBehaviour
{
public XDocument doc;
public List<DStar> starList;
void Start()
{
doc = XDocument.Load (Application.dataPath + "/Code/Data/galaxy.xml");
starList = (from q in doc.Descendants ("Star") select new DStar{
ID = int.Parse (q.Element("ID").Value),
x = int.Parse (q.Element("X").Value),
y = int.Parse (q.Element("Y").Value),
magnitude = float.Parse (q.Element("Magnitude").Value),
size = int.Parse (q.Element("Size").Value),
}).ToList ();
Debug.Log(starList.Count);
}
}
The list has all the correct information in it if I'm debugging it in that class specifically. And in the other class where I'm trying to get the list:
public class GalaxyMapScript: MonoBehaviour
{
public GameObject Database;
private DStarMap _starMap;
void Awake()
{
_starMap = Database.GetComponent<DStarMap>();
Debug.Log(_starMap.starList.Count);
}
}
The count is always null. I don't understand. I'm assigning the reference to the database object through the inspector. Ugh.
Is your 'DStar$$anonymous$$ap' script attached to the Database gameobject?
to avoid having to assign your database reference through the inspector, you could try doing it programmatically like this:
GameObject Database = GameObject.FindGameObjectWithTag("Database"); Database = Database.GetComponent<DStar$$anonymous$$ap>();
You'll have more control through your scripts that way.
I usually do that but I wanted to do it through the inspector this time because its ideal in this scenario for me to use it.
Do you know why starList would be null? DStar$$anonymous$$ap is indeed attached to the database object.
Perhaps I've looked over something, but it doesn't appear as though the list is populated anywhere in the code? Do you have objects for the list stored elsewhere?
the list is populated by reading from an X$$anonymous$$L document using Linq. I can:
Foreach(DStar s in starList)
{
Debug.Log(s.ID);
}
And I get all the right information.
The problem is that for some reason when I grab the component its not obtaining the list. It just, for some reason, says its null. I have no idea why >;c
Answer by Bonfire-Boy · Jun 14, 2015 at 06:48 PM
It's null because you haven't set it to anything yet.
GalaxyMapScript's Awake() function will run before DStarMap's Start() function. The simplest fix would be to swap them ie set up the starList in DStarMap's Awake() and get the reference to it in GalaxyMapScript's Start().
But in most situations, unless there's a real need to cache the reference within GalaxyMapScript, I would probably prefer to get rid of the _starMap variable and just use Database.starList within the GalaxyMapScript class. Sometimes though there can be a need to cache the reference (eg you want to make sure that GalaxyMapScript retains its list if Database is destroyed, or if the list in Database is set to a new List).
What do you mean I'm not setting it to anything? I am slightly confused, what am I not setting?
This
public List starList;
It's not initialised to anything whne you declare it, so it starts off as null.
You then set it to something in a Start() function. But Awake functions run first. So when Galaxy$$anonymous$$apScript's Awake function runs, its still null. So when you do this...
Debug.Log(_star$$anonymous$$ap.starList.Count);
_star$$anonymous$$ap.starList is null because you haven't set it to anything yet.
You just need to make sure you set it before you use it. You're using the Start() function as if it's a constructor. It's not. When you initialise things in Start() you need to be careful not to try to use them before it runs. It runs at the start of its first active frame after instantiation, but Awake runs before that, at instantiation. So when you press play all the objects in your scene have their Awakes done before any of them have their Starts.
Simply swapping the names of the Start and Awake functions in your 2 snippets, so that DSTar$$anonymous$$ap has an Awake() and Galaxy$$anonymous$$apScript has a Start() will probably fix it. That's the simplest code change. Another way would be lazy initialisation so that you only cache it the first time you use it.
But like I said you should also consider whether you really need the cached pointer to Database's starList at all, give that you can access it easily enough through Database.
Ah, I see. I'm an idiot. I thought Awake was after Start. Thank you so much man.
Answer by appslabs · Jun 14, 2015 at 06:38 PM
Make sure you initialize a 'new instance' of your list on every start.
public class DStarMap : MonoBehaviour
{
public XDocument doc;
public List<DStar> starList;
void Start()
{
starList = new List<DStar>();
//Your code here
}
}
They are initialising it in Start(), just in a different way. The problem is that Start() is called too late.
Your answer
![](https://koobas.hobune.stream/wayback/20220613200953im_/https://answers.unity.com/themes/thub/images/avi.jpg)