Home > OS >  NullReferenceException while setting TextMeshProUGUI
NullReferenceException while setting TextMeshProUGUI

Time:09-01

I have been following the tutorial here enter image description here

I've been trying to bind SpaceText to Space in the following way: enter image description here Is it correct way to do it and is it necessary?

MainController screen: enter image description here

The code in MainController.cs:

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

public class MainController : MonoBehaviour
{

    public TextMeshProUGUI[] space_list;
    public GameObject game_over_panel;
    public TextMeshProUGUI game_over_text;
    public GameObject restart_button;
    private TextMeshProUGUI side;
    private int moves;
    
    void Start()
    {
        SetMainControllerReferenceForButtons();
        side.text = "X";
        game_over_panel.SetActive(false);
        moves = 0;
        restart_button.SetActive(false);
    }

    
    void SetMainControllerReferenceForButtons()
    {
        for (int i = 0; i < space_list.Length; i  ){
            space_list[i].GetComponentInParent<Space>().SetControllerReference(this);
        }
    }

    public TextMeshProUGUI GetSide()
    {
        return side;
    }

    void ChangeSide()
    {
        if (side.text == "X")
        {
            side.text = "O";
        } else {
            side.text = "X";
        }
    }

    public void EndTurn()
    {
        moves  ;
        if (space_list[0].text == side.text && space_list[1].text == side.text && space_list[2].text == side.text)
        {
            GameOver();
        }
        else if (space_list[3].text == side.text && space_list[4].text == side.text && space_list[5].text == side.text)
        {
            GameOver();
        }
        else if (space_list[6].text == side.text && space_list[7].text == side.text && space_list[8].text == side.text)
        {
            GameOver();
        }
        else if (space_list[0].text == side.text && space_list[3].text == side.text && space_list[6].text == side.text)
        {
            GameOver();
        }
        else if (space_list[1].text == side.text && space_list[4].text == side.text && space_list[7].text == side.text)
        {
            GameOver();
        }
        else if (space_list[2].text == side.text && space_list[5].text == side.text && space_list[8].text == side.text)
        {
            GameOver();
        }
        else if (space_list[0].text == side.text && space_list[4].text == side.text && space_list[8].text == side.text)
        {
            GameOver();
        }
        else if (space_list[2].text == side.text && space_list[4].text == side.text && space_list[6].text == side.text)
        {
            GameOver();
        }

        if (moves >= 9)
        {
            game_over_panel.SetActive(true);
            game_over_text.text = "Remis";
            restart_button.SetActive(true);
        }
        ChangeSide();
    }

    void GameOver()
    {
        game_over_panel.SetActive(true);
        game_over_text.text = side.text   " wygrywa!";
        restart_button.SetActive(true);
        for (int i = 0; i < space_list.Length; i  )
        {
            SetInteractable(false);
        }
    }

    void SetInteractable(bool setting)
    {
        for (int i = 0; i < space_list.Length; i  )
        {
            space_list[i].GetComponentInParent<Button>().interactable = setting;
        }
    }

    public void Restart()
    {
        side.text = "X";
        moves = 0;
        game_over_panel.SetActive(false);
        SetInteractable(true);
        restart_button.SetActive(false);
        for (int i = 0; i < space_list.Length; i  )
        {
            space_list[i].text = "";
        }
    }
}

The code in Space.cs:

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

public class Space : MonoBehaviour
{
    public Button button;
    public TextMeshProUGUI button_text;
    private MainController main_controller;

    public void SetControllerReference(MainController control)
    {
        main_controller = control;
    }

    public void SetSpace()
    {
        button_text = main_controller.GetSide();
        button.interactable = false;
        main_controller.EndTurn();
    }
}

Edit: I have changed the code in MainController.cs. Changed type of side to string and activated buttons in Start() function. Now they are clickable and value on them can be seen if I hardcode it in an Inspector. Still I don't know how to make the "X" or "O" visible after a click on a button (SetSpace is called). The NullReferenceException still appears.

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

public class MainController : MonoBehaviour
{

    public TextMeshProUGUI[] space_list;
    public GameObject game_over_panel;
    public TextMeshProUGUI game_over_text;
    public GameObject restart_button;
    private string side;
    private int moves;
    
    void Start()
    {
        SetMainControllerReferenceForButtons();
        side = "X";
        SetInteractable(true);
        game_over_panel.SetActive(false);
        moves = 0;
        restart_button.SetActive(false);
    }

    
    void SetMainControllerReferenceForButtons()
    {
        for (int i = 0; i < space_list.Length; i  ){
            space_list[i].GetComponentInParent<Space>().SetControllerReference(this);
        }
    }

    public string GetSide()
    {
        return side;
    }

    void ChangeSide()
    {
        if (side == "X")
        {
            side = "O";
        } else {
            side = "X";
        }
    }

    public void EndTurn()
    {
        moves  ;
        if (space_list[0].text == side && space_list[1].text == side && space_list[2].text == side)
        {
            GameOver();
        }
        else if (space_list[3].text == side && space_list[4].text == side && space_list[5].text == side)
        {
            GameOver();
        }
        else if (space_list[6].text == side && space_list[7].text == side && space_list[8].text == side)
        {
            GameOver();
        }
        else if (space_list[0].text == side && space_list[3].text == side && space_list[6].text == side)
        {
            GameOver();
        }
        else if (space_list[1].text == side && space_list[4].text == side && space_list[7].text == side)
        {
            GameOver();
        }
        else if (space_list[2].text == side && space_list[5].text == side && space_list[8].text == side)
        {
            GameOver();
        }
        else if (space_list[0].text == side && space_list[4].text == side && space_list[8].text == side)
        {
            GameOver();
        }
        else if (space_list[2].text == side && space_list[4].text == side && space_list[6].text == side)
        {
            GameOver();
        }

        if (moves >= 9)
        {
            game_over_panel.SetActive(true);
            game_over_text.text = "Remis";
            restart_button.SetActive(true);
        }
        ChangeSide();
    }

    void GameOver()
    {
        game_over_panel.SetActive(true);
        game_over_text.text = side   " wygrywa!";
        restart_button.SetActive(true);
        for (int i = 0; i < space_list.Length; i  )
        {
            SetInteractable(false);
        }
    }

    void SetInteractable(bool setting)
    {
        for (int i = 0; i < space_list.Length; i  )
        {
            space_list[i].GetComponentInParent<Button>().interactable = setting;
        }
    }

    public void Restart()
    {
        side = "X";
        moves = 0;
        game_over_panel.SetActive(false);
        SetInteractable(true);
        restart_button.SetActive(false);
        for (int i = 0; i < space_list.Length; i  )
        {
            space_list[i].text = "";
        }
    }
}

Edit 2: I have added [SerializeField] at the top of my variable side. Now in the Inspector, I have typed in "X" to make sure side has a value. It didn't solve the issue. enter image description here

CodePudding user response:

You first need to get the TextMeshProUGUI component from the Gameobject. A solution could be something like GameObject.Find("SpaceText").GetComponent<TextMeshProUGUI>().text = "Your Text".

But according to your Picture you have multiple objects named "SpaceText" so propably you should rather do it with a GameObject variable where you then insert the wished gameobject per drag and drop in the editor.

Hope it helps :)

CodePudding user response:

Should I change it to something else?

Don't be afraid of error compilers give you. It doesn't mean, the stuff you are using must be faulty, but it indicates what's the problem.

And the problem is, that something is null in line 20. Go from left to right and check what might be null. Starting from side: TextMeshProUGUI is a reference type so it might be. Since side is private and not marked as [SerializeField] I know you didn't initialized it in inspector. Neither can I see you initializing it in your code.

Initialize your side variable from code or inspector to fix this.

Also you can't see X in your game as you tried assign it to null.

In the future, you might use this to resolve other nullref issues:

What is a NullReferenceException, and how do I fix it?

  • Related