Component refrence goes null randomly?

I have a script that finds an script called RFormachariumINfo, and stores it as finfo. after i use gameobject.findobjectoftype, it prints the correct statment, as it found a FormachariumInfo, however when i use it in the Purchase() function, i print it’s value and it is null and i dont know why.

Here is my script :

using UnityEngine;
using UnityEngine.UI;

public class PurchaseManager : MonoBehaviour {

    [SerializeField]
    private GameManager gameManager;
    private CurrencyDisplays[] currencyDisplays;
    private FormachariumInfo finfo;
    private OutworldInfo oinfo;
    public Text text;
    private string type;
    private int cost;
    public GameObject purchaseButton;

    public void Setup()
    {
        currencyDisplays = GameObject.FindObjectsOfType<CurrencyDisplays>();
        finfo = GameObject.FindObjectOfType<FormachariumInfo>();
        print(finfo);
        oinfo = gameManager.oinfo;
    }

    public void SetToolBarType(string _type)
    {
        text.text = "";
        type = _type;
        text.text = text.text + type + "

";
}

    public void SetToolBarCost(int _cost)
    {
        cost = _cost;
        text.text = text.text + cost + "

"; ;
}

    public void SetToolBarDesk(string desk)
    {
        text.text = text.text + desk;
        purchaseButton.SetActive(true);
    }

    public void Purchase()
    {
        if (gameManager.coins < cost)
            return;

            gameManager.coins -= cost;
            if (type == "Small Formacharium")
            {
                gameManager.formacharia1++;
                gameManager.CalculateMaxAnts();
            }
            else if (type == "Medium Formacharium")
            {
                gameManager.formacharia2++;
                gameManager.CalculateMaxAnts();
            }
            else if (type == "Large Formacharium")
            {
                gameManager.formacharia3++;
                gameManager.CalculateMaxAnts();
            }
            else if (type == "Extra Large Formacharium")
            {
                gameManager.formacharia4++;
                gameManager.CalculateMaxAnts();
            }
            else if (type == "Small Outworld")
            {
                gameManager.outworlds1++;
                gameManager.FindMaxFood();
            }
            else if (type == "Medium Outworld")
            {
                gameManager.outworlds2++;
                gameManager.FindMaxFood();
            }
            else if (type == "Large Outworld")
            {
                gameManager.outworlds3++;
                gameManager.FindMaxFood();
            }
            else if(type == "Extra Large Outworld")
            {
                gameManager.outworlds4++;
                gameManager.FindMaxFood();
            }
            else if (type == "Mealworm")
            {
                gameManager.mealworms++;
            }
            else if (type == "Superworm")
            {
                gameManager.superworms++;
            }
            else if (type == "Cockroach")
            {
                gameManager.cockroaches++;
            }
            else if (type == "Water")
            {
                gameManager.water++;
            }
            else if (type == "AntProduction")
            {
                gameManager.antProductionLevel++;
            }
            else if (type == "MaxAnts")
            {
                gameManager.antCapacityLevel++;
            }
        print(finfo);
        finfo.SetDisplay();
        oinfo.SetDisplay();
        gameManager.CalculateMaxAnts();
        gameManager.CalculateBonus();
        foreach (CurrencyDisplays display in currencyDisplays)
        {
            display.SetText();
        }
    }



}

aaaand the biggest facepalm of 2017!!!

i had the script attached to two gameobjects…

Component references never “randomly goes null” but do become a fake-null reference when the component or the gameobject it’s attached to was destroyed. This can happen either by explicitly calling Destroy or DestroyImmediate on the component or gameobject reference or by loading a new level which will automatically destroy all objects from the last level.

Where do you call Setup?

As a quick solution, you can make it lazy loaded. (but should not be required if you do it the right way).
This way it is loaded and cached for later use, but only when you first access it. So not at the start of the level.

Lazy solution:

    private FormachariumInfo _finfo;
    private FormachariumInfo finfo
    {
        get
        {
            if (_finfo == null)
                _finfo = GameObject.FindObjectOfType<FormachariumInfo>();
            return _finfo;
        }
    }

access it by calling finfo