1

So, I'm aware that null reference exceptions are a pretty commonly brought up issue on here, but I'm genuinely stuck on this, as this code went from working fine to really not working, and I can't figure out why. I used this tutorial as a starter to get to where I am, https://www.youtube.com/watch?v=2TYLBusJKjc, and then added/adapted for my purposes. I then copied the buttonlistcontrol and buttonlistbutton script files, and renamed and edited them to use as a separate settings menu, which is when it all went downhill.

[SerializeField]
public GameObject upButtonTemplate, buttonTemplate, headingTemplate;

public void GenButtons()
{               
    ClearAll();
    
    bankIms = Resources.LoadAll("buttons/bank", typeof(Sprite));
    coinIms = Resources.LoadAll("buttons/coin", typeof(Sprite));
    bgIms = Resources.LoadAll("BgPrevs", typeof(Sprite));
    
    upgrades = new string[]{"text,some more text, even more text none of which matters here"};
    upPrices[0] = gameManager.bank;
    
    GenHeading("UPGRADES");
    
    for (int i = 0; i < upgrades.Length; i++)
    {
        GameObject button = Instantiate(upButtonTemplate) as GameObject;
        button.SetActive(true);
        Debug.Log("button: " + button);
        button.GetComponent<ButtonListButton>().ButtonSetup("upgrade", i); // Null Reference occuring on this line
        button.GetComponent<ButtonListButton>().SetUpText(upgrades[i]);
        button.GetComponent<ButtonListButton>().SetPrice(upPrices[i]);
        
        
        button.transform.SetParent(upButtonTemplate.transform.parent,false);
        
        upButts.Add(button);
    }

void GenHeading(string head) 
{
    GameObject heading = Instantiate(headingTemplate) as GameObject;
    heading.SetActive(true);

    heading.GetComponent<TextMeshProUGUI>().text = head;
    heading.transform.SetParent(headingTemplate.transform.parent,false);
    
    headings.Add(heading);
}

When GenButtons is run now, the heading is still being created as expected, but I get an error Object reference not set to an instance of an object, and a clone of the button prefab gets added outside the canvas.

Heading added as expected, but StoreListUpgrade is wildly and annoyingly off

Any help that could sort it would be thoroughly appreciated.

Below is the ButtonListButton script, if it helps.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;

public class ButtonListButton : MonoBehaviour
{
[SerializeField]
private TextMeshProUGUI upButtText, buttText;
[SerializeField]
private ButtonListControl buttonControl;
[SerializeField]
private Image buttonImage;
[SerializeField]
private SoundManager soundManager;
public GameManager gameManager;

public double buttonPrice;
public int buttonID;
public bool owned;
public bool selected;
public string buttonType;

public void ButtonSetup(string type, int id) 
{
    if (type == "bank") {
        owned = buttonControl.bankOwn[id];
        selected = buttonControl.bankSel[id];
    } else if (type == "coin") {
        owned = buttonControl.coinOwn[id];
        selected = buttonControl.coinSel[id];
    } else if (type == "bg") {
        owned = buttonControl.bgOwn[id];
        selected = buttonControl.bgSel[id];
    }
    buttonType = type;
    buttonID = id;
}

public void SetPrice(double price)
{
    if (owned) {
        if (selected) {
            buttText.text = "✔";
        } else {
            buttText.text = "Owned";
        }
    } else {
        buttonPrice = price;
        buttText.text = "$" + price.ToString("N0");
    }
    TextColour();
}

public void PriceUpdate(bool onPurchase, bool onSetup)
{
    if (buttonType == "upgrade"){
        if (buttonID == 0) {
            buttonPrice = 0;
            SetPrice(0);
        } else if (buttonID == 1) {
            buttonPrice = (double)(buttonPrice * 1.2f);
            buttonControl.upPrices[buttonID] = buttonPrice;
            SetPrice(buttonPrice);
        } else if (buttonID == 2) {
            buttonPrice = (double)(buttonPrice * 1.5f);
            buttonControl.upPrices[buttonID] = buttonPrice;
            SetPrice(buttonPrice);
        } else if (buttonID == 3) {
            buttonPrice = (double)(buttonPrice * 1.5f);
            buttonControl.upPrices[buttonID] = buttonPrice;
            SetPrice(buttonPrice);
        }
    } else {
        if (onPurchase) {
            buttText.text = "✔";
            selected = true;
            owned = true;
            buttonControl.OwnSel(buttonType, buttonID, "sel", true);
            buttonControl.OwnSel(buttonType, buttonID, "own", true);
            buttonPrice = 0;
        } else {
            if (onSetup == false && selected) {
                selected = false;
                buttonControl.OwnSel(buttonType, buttonID, "sel", false);
                buttText.text = "Owned";
            }
        }
    }
    TextColour();
}

public void SetImage(Object ob)
{
    Debug.Log("Set Image: " + ob);
    buttonImage.sprite = ob as Sprite; 
}

public void SetUpText(string upgrade)
{
    upButtText.text = upgrade;
}

public void TextColour()
{
    if (gameManager.bank >= buttonPrice && buttonPrice > 0 || owned) {
        buttText.color = Color.black;
    } else {
        buttText.color = new Color(180, 0, 0, 1);
    }
}

public void OnClick() 
{
    Debug.Log("bank: " + gameManager.bank + ", buttprice: " + buttonPrice + ", compareto: " + gameManager.bank.CompareTo(buttonPrice));
    Debug.Log("adjust compare: " + gameManager.bank.CompareTo(buttonPrice - 0.001f) + "bank: " + gameManager.bank + ", buttprice-: " + (buttonPrice - 0.001f));
    if (gameManager.bank.CompareTo(buttonPrice - 0.001f) >= 0) {
        if (buttonID == 0 && gameManager.bank == 0) {
            soundManager.playnobuy(1);
        } else {
            soundManager.playmenuopen(0.8f);
            buttonControl.ButtonClicked(buttonPrice, buttonType, buttonID);
            PriceUpdate(true,false);
        }
    } else {
        soundManager.playnobuy(1);
    }
}
}

I think the formatting went a bit off there, apologies for that.

EdW
  • 11
  • 3
  • Sounds like your button doesn’t have the component you’re expecting. – BugFinder Aug 28 '22 at 07:09
  • As far as I can tell, the buttonlistbutton is connected, which is part of why it's confusion – EdW Aug 28 '22 at 14:15
  • Well you could debug it to see if it is picking up the component. If it says no then the answer is either wrong prefab or you didn’t update the prefab – BugFinder Aug 28 '22 at 15:44
  • It would be helpful you could show the inspector of the object serialized as `upButtonTemplate`, and the callstack of your null reference. Also, as an aside, you should try to avoid repeated `GetComponent` calls and instead store a reference to your `ButtonListButton` in a temporary variable, which will also make it easier to null check. – NSJacob1 Sep 08 '22 at 02:49

0 Answers0