Accessing inactive objects + NullreferenceExceptions

I have made a weapon and ammo system for my game. Weapons are switched by enabling/disabling them via script, and the weapons are child objects attached to the player.
Each weapon’s ammo system is scripted in the same script as the weapon mechanic, and each weapon has its own ammo.
I have created ammo pickups specific to each weapon:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PistolPickup : MonoBehaviour {

    Pistol pistol;
   // AK47 ak47; WIP
    //ShotgunWeapon shotgun; WIP


    void Awake ()
    {
        pistol = GameObject.Find ("Player").GetComponentInChildren<Pistol> ();
    }

    void Update ()
    {
        transform.Rotate (new Vector3 (0, 90, 0) * Time.deltaTime);
    }

    void OnTriggerEnter(Collider other)
    {
        if (other.gameObject.CompareTag ("Player"))
        {
   
            pistol.currentClips += 1;
            Debug.Log ("Pickup");
            gameObject.SetActive (false);
        }
        else
        {
            return;
        }
    }
}

And it works while I have pistol selected and get the pickup. The problem arises when I get the pickup with any other weapon selected (and thus, in this case, the object pistol disabled). In that situation, it gives an NullReferenceException error:

NullReferenceException: Object reference not set to an instance of an object
PistolPickup.OnTriggerEnter (UnityEngine.Collider other) (at Assets/Scripts/Managers/Pickups/PistolPickup.cs:27)

How do I get this script to add clips to the pistol while I have selected any other weapon?
I suppose one way could be moving the ammo system separate from the weapon scripts, but are there any other, more efficient ways?
And after experimenting, I feel the “return” at the end of the code is not required, since there is no more code after the OnTriggerEnter(Collider other)?

GameObject.Find is bad to use anyways, so the two ways to solve it is either move the scripts off the weapons that track ammo, have a manager class that manages your ammo (this could be a singleton class for the player ammo), or have a script on your player that has a reference to each weapon script, thus you can target that weapon through the script on your player.(this last one is similar to the singleton, but you’d still be finding the player).

Honestly, I would probably use the singleton method myself, but that’s just me.

Also, you are correct, that return is not needed.

1 Like

Thank you, Brathnann. I will try your suggestions and post back here if I run into problems, or if I solve it.

All of the GetComponent methods also take an optional boolean argument to include inactive components. So if it were disabled you could still get it with

GetComponentInChildren<Pistol>(true);
1 Like

Interesting as that wasn’t listed in the scripting API. However, I only get the optional bool on the GetComponentInChildren call, the parent one doesn’t have this.

Yeah it’s weird. GetComponentsInChildren documents it but GetComponentInChildren doesn’t. Unity - Scripting API: GameObject.GetComponentsInChildren

This worked, thanks. I think I will still rework the ammo system to be separate from the weapons, but this will do for now. you know, we always need that "This works, I can fix and make this better later… ":stuck_out_tongue:

It’s also bad to try to find objects in Awake(). Do that in Start() instead.