Problems using static variables in UI elements

Good evening to all,

I’m having a problem using a public static variable in a UI Canvas.

I have a Game Object that holds the player score. When time is up, I either instantiate a wining canvas or a loose canvas. But when I try to access the player score in a button in the canvas, it says that the object is null.

How to overcome that?

Thanks in advance.

You really should post relevant code for this to be answered. Not all of it, only the parts that deal with the variables and objects needed. :slight_smile:

using UnityEngine;
using System.Collections;
using System;

public class AdsButtonController : MonoBehaviour
{
    private DateTime thisTime;
    private DateTime nextTimeGiveBonus;
    // Use this for initialization

    void Awake ()
    {
        nextTimeGiveBonus = AdsAvailabilityControl.adsvailabilityControl.nextTimeToGiveExtraBonus;
    }
    void Start ()
    {
   
    }
   
    // Update is called once per frame
    void Update ()
    {
        thisTime = System.DateTime.Now;
        if (thisTime >= nextTimeGiveBonus)
        {
            gameObject.SetActive (true);
        } else
        {
            gameObject.SetActive (false);
        }
   
    }
}

This script is attached to the button. But when the canvas is instantiated it says that AdsAvailabilityControl is null. But it is in the Hierarchy.

What is AdsAvilabilityControl? It may be in the hierarchy, but you have to tell the scrip to find it.

AdsAvilabilityControl is a Singleton.

public class AdsAvailabilityControl : MonoBehaviour

{
    public static AdsAvailabilityControl adsvailabilityControl = null;    // Instancia do script
    public DateTime lastTimeAddedBonus;                    // Variavel indica a ultima vez que o jogador ganhou extra bonus, para evitar de dar
                                                        //        mais de um extra bonus a cada 30 min
    public Queue<DateTime> addDateQueue = new Queue<DateTime>();    // Varivel usada para guardar as datas dos bonus extras
    public DateTime nextTimeToGiveExtraBonus;            // Determina a hora para o proximo extra bonus


    void Awake()
    {
        if (adsvailabilityControl == null) // Checando se o objeto (BonusManager) ja existe
        {                   
            DontDestroyOnLoad (gameObject);        // Se nao existir, faz com que esse nao seja destruido ao se trocar de cena
            adsvailabilityControl = this;                        // Seta esse objeto na instancia do script
            LoadAddAvailabilityData();
            EventManager.AddHandler (EVENT.OnWatchedVideo, UpdateAdsAvailability);
        } else if (adsvailabilityControl != this)
        {
            Destroy(gameObject);                // Se ja existir esse objeto entao ele se auto destroi
        }

    }

As soon as I instantiate the canvas the object becomes null. If I destroy the canvas it comes back the normal.

Two things I can think of:

1.) Order of initialization. You might be requesting the singleton-like instance before Awake is called.

Try this pattern instead:

public class MySingletonClass : MonoBehaviour
{
    public static MySingletonClass instance
    {
        get
        {
            if(_instance == null)
            {
                _instance = (MySingletonClass)FindObjectOfType(typeof(MySingletonClass));
                DontDestroyOnLoad(_instance.gameObject);
            }

            return _instance;
        }
    }

    private static MySingletonClass _instance;

    void Awake()
    {
        if (_instance != null && _instance != this)
        {
            Debug.LogError("Singleton already initialized.");
            Destroy(this.gameObject);
        }
    }
}

2.) There might be another instance of the single-like class. Maybe you are instantiating a second one at runtime and referencing the wrong one. Again, you can see if it works better with the lazy-initialization I show in the code sample.

What is that m_Instance.gameObject that you don’t destroy on load?

A typo. I meant “_instance” :stuck_out_tongue: There might be others, I don’t have an IDE to check right now and you might want to add in additional checks like what to do when there is not instance to be found or find all objects of type and see if the array returns more than one and things like that to make it more safe. Generally, you want to try to code safe by thinking about everything that can go wrong and at least log an error if it happens. That way you will probably find out what your specific problem is about.

I appreciate your help, but as a newbie you just fried my brain.

public static AdsAvailabilityControl adsvailabilityControl
    {
        get
        {
            if(_adsvailabilityControl == null)
            {
                _adsvailabilityControl = (AdsAvailabilityControl)FindObjectOfType(typeof(AdsAvailabilityControl));
                DontDestroyOnLoad(_adsvailabilityControl.gameObject);
            }
            return _adsvailabilityControl;
        }
    }

Its here where I should check if there is no instance of MySingleton Class?
And if there isn’t, how should I instantiate.

Just to clear things out. There is only one instance of the AdsAvailabilityControl when I get the error. At least in the hierarchy shows only one.

I just would like to know why when I instantiate the canvas all other objects in the scene become not available.

That really isn’t the case. What is probably happening, as @Xarbrough_1 mentioned, is an order of initialization problem.

You setup your nextTimeGiveBonus var in Awake(), but you also only setup your AdsAvailabilityControl static variable in its Awake(), so what is happening is that AdsButtonController initializes BEFORE AdsAvailabilityControl, and at that point the variable is still null.

You can fix this simply by moving the code in AdsButtonController from Awake() to Start(). In general, you want Awake() to initialize just the local class, and not access anything else. Further initialization, especially ones that require access of other objects, is better done in Start(), which will guarantee that accessed objects are initialized, in your case, AdsAvailabilityControl static var.