I have been following the tutorial here https://www.red-gate.com/simple-talk/development/dotnet-development/using-unity-ui-and-c-to-create-a-tic-tac-toe-game/. I have had some problems (How to drag text into list in Unity?) with Text type and string type, so I have changed these types to TextMeshProUGUI. Now, I have set up everything including a list in MainController. However, when I start a game, there is
NullReferenceException: Object reference not set to an instance of an object
MainController.Start () (at Assets/MainController.cs:20)
In line 20, I try to set up side.text = "X"; Should I change it to something else? Before my change to TextMeshProUGUI side, was of type string, however I thought of changing all types to TextMeshProUGUI. X text doesn't even show on the screen when I start the game.
I've been trying to bind SpaceText to Space in the following way:
 Is it correct way to do it and is it necessary?
Is it correct way to do it and is it necessary?
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.

Edit 3:
Now when I click some of the buttons, "X" and "O" are visible, but some buttons are clickable, but nothing shows on them even though I checked whether list in MainController is full and Space(script) fields, which is Button and Button_text are entered and everything is correct here. What can be the issue? With white buttons, when I click on them there is NullReferenceException and line button_text.text = main_controller.GetSide(); is causing it.
.



 
     
    