NullReferenceException: Object reference not set to an instance of an object

TL;DR edit: some critical lessons I learned –

1. gameObject.enabled – what is this useful for?

Apparently while you can trust this boolean to be true for an object which is enabled, you can NOT trust it to accurately be false when the same object is disabled. Also, for clarity, I might be misconstruing this… What I know is that if I set a member variable to contain a reference to a script, i.e.:

PlayerController playerController;
playerController = GameObject.FindObjectOfType<PlayerController>()

Then visual studio prompts me that I can use: playerController.enabled … it didn’t solve the problem, neither did playerController.IsAliveAndActive which, at the time, seemed like it would be a sure-fire winner.

2. null reference – the heart of the matter.

Well, as the error says, the issue is a NullReferenceException… so, what is very clear in hindsight is that the solution is to… well, check for a null reference! Thus the solution was to add this line of code:

        if (playerController == null) 

Of course there are a few more minor details, such as re-assigning the reference to the PlayerController to the playerController member variable, but this one line seems to have stopped the cascade of errors.


All the other related threads are in the 1.0 course; also, while they share the same error message it’s for a different reason. Here’s the scoop…

I have a PlayerManager.cs that has (for now) basically one job… Manage player resets. When the player damage-received exceeds the player shield capacity, the PlayerController.cs makes a call to playerManager.ResetPlayer(); Then the playerManager sets the player GameObject to inactive, waits a few seconds, and turns it back on at the “home” position.

So I’m only getting the “NullReferenceException: Object reference not set to an instance of an object” error after the player has died at least once. It comes from my EnemyController.cs, where I have this Update() method:

private void Update()
{
    if (playerManager.PlayerIsAlive())
    {
        transform.LookAt(playerController.transform);
        TryShoot();
    }
}

The 3rd line: if (playerManager.PlayerIsAlive()) was intended to stop the errors. It seems that if the playerController is set inactive, and the enemy is told to LookAt() it, it’s a problem. Fair enough… But if I’m doing this check on playerManager, why do I still get the errors?

Well, I’ve tried a couple things, both of which I thought were all that was needed at the time, and apparently neither is. Allow me to walk you through my journey: First, in PlayerManager.cs, I’d set PlayerIsAlive to “return playerController.enabled”. That didn’t work. When I looked at the fine-print, I noticed that it says this boolean is updated for active objects, but not updated for inactive ones… Left wondering what utility there is in that, I moved-on and found what I tried next: “return playerController.IsActiveAndEnabled” Ahah! That’ll do it! NOT…

So then I got to thinking… Why not be more direct? So now, in my PlayerManager.cs (probably not the version on GitHub) I explicity set a local private boolean to false before I even deactivate the playerController, and I don’t set it back to true until after the player is respawned. Now playerManager.PlayerIsAlive() returns that boolean. FIXED, right?!?! NOPE.

At this point, I’m thinking I need to figure out the Unity event system… i.e. the moment the playerController decided it’s time to die/reset it needs to broadcast some type of event, and my enemy controller needs to be “tuned-in” to that… then each and every enemy will be notified the instant the player is inactive, and it can bypass it’s LookAt() command while it waits for the broadcast that the player is back in action…

Wish me luck! :slight_smile:

I’d check what line number the exception is happening on to narrow down which object is null.

1 Like

As I sit here pondering this, I wonder if assigning the PlayerController.cs{GameObject] to the EnemyController.cs in the inspector might solve this… or maybe I can check if it’s null and re-link the reference… ???

{time passes}

Okay, so as it turns out, it looks like I won’t need to use the event system for this, and seeing it from this new perspective, I think it mayn’t have solved the issue anyway. At present I now have my EnemyController.cs Update() looking like this:

private void Update()
{
    if (playerManager.PlayerIsAlive())
    {
        if (playerController == null) 
        {
            Debug.Log("playerController REUP:");
            playerController = GameObject.FindObjectOfType<PlayerController>();
            if (!playerController) Debug.Log("playerController REUP-FAIL.");
        }
        transform.LookAt(playerController.transform);
        TryShoot();
    }
}

After play-testing to a thousand-or so points it finally happened… .console read, “playerController REUP”, but generated zero errors before or after. Now, apparently I need to do a similar thing in my EnergyBonus.cs, because it uses a call to playerController as well, which on extremely rare occasion does a similar null reference error… playerController.ChargeWeaponBattery(0.5f); should be fixed moments after I post this.

EDIT: final analysis –

After play-testing a few minutes, I only got a small handful of debug messages, but it’s enough to show that:

  1. Sometimes, when new objects (bonuses or enemies) were spawned, it must have been while the playerController was set inactive, but they also now reassign the reference as needed.
  2. Other errors indicate that occasionally the reference did seem to get-de-referenced in already-established objects.
  3. I’m surprised how few debug messages were generated… it seems that while my PlayerManager leaves the player ship inactive for a full 3 seconds, there are very few frames where any objects are reporting issues… Meanwhile, before I was reassigning the variable, once the errors started they would come by the bucket-load (thousands in a minute or two of play-testing).

That was a quicker resolution than I was expecting, thank you Rubber Ducky Forum :slight_smile:

Thanks DigitalMan… I was fairly certain it was my:

PlayerController playerController;

reference, which seems to be de-referenced if it’s accessed while the GameObject is set inactive? (I’m honestly not entirely sure what’s going-on at the core level) but I was thinking that based on the timing… I could play for a while with no errors, then die and suddenly they start flooding the console…)

I’ve got it patched now, by having EnemyController.cs check if playerController == null and if it is, it finds the object and reassigns it to the playerController variable.

I don’t think the event system would have helped after-all.

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms