Hello, I had previously put this “player != null” condition in the AI Controller script, as seen in the image below. This is the part where an enemy checks if the player is within the chase distance and whether or not to attack it.
I thought that since I am knowingly assigning -
GameObject player = GameObject.FindwithTag(“Player”);
then I dont need to check for the “player != null conditon”, so I removed that condition and I got Null reference exception error.
I was wondering why? If I am assigning the player reference variable to the corresponding game object on the previous line of code and during each frame when the update method runs, it will run the first line then the if statement, that condition will always be true. Why do I need to check it?
One thing 40 years of programming has taught me is that you can never assume that a condition will always be true, even when it looks like it must be.
My first guess is that the player isn’t tagged correctly.
A few optimizations here, that will save some clock cycles (GameObject.FindWithTag(string) is an expensive operation). I would put this in Start() or Awake()…
GameObject player;
void Awake()
{
player = GameObject.FindWithTag("Player");
if(player==null)
{
Debug.LogWarning($"Unable to locate the Player.");
}
}
Then you can remove the search for the player in the Update() method.
This still, however, leaves the possibility that the player is null…
If you get the warning in Awake that the Player couldn’t be located, then it’s likely that the player doesn’t have the “Player” tag.
I just want to add that you are not actually knowingly assigning player to anything. You are asking a function to assign player to something. That function could be returning null. If you had GameObject player = new GameObject("Player");
you could probably assume it’s set. However, like Brian said, don’t assume that it will.
In this case it should not have returned null and it indicates one of at least two things: There is no player in the scene, or the player is not tagged with ‘Player’.
Just as an alternative to Brian’s suggestion, I like to use Assert
. When I am setting values in Awake
or Start
that I know have to be available - like player - I do this
private void Awake()
{
_player = GameObject.FindWithTag("Player");
Debug.Assert(_player != null);
}
It’s essentially the same thing Brian is doing and there’s no reason I can think of why this is a better option. It’s just another one.
The player was indeed tagged, that’s the first thing I checked. Anyways its a good thing to not assume things and to always check if the object is not null. Thanks for your suggestions, I will definitely use them.
That still leaves us with the mystery of why AIController thinks it’s null…
It’s in Awake()
. Perhaps it’s a race condition?
It was originally in Update, and GameObject.FindWithTag(string) will work in Awake always. Now if you tried to access a component’s methods in Awake, THAT might trigger a race condition, but we’re not doing that here.