NullReferenceException when none of variables should be null.

So uh… We have a problem with one line of code we don’t know how to fix(second code, on try catch).
It tells us that one of variables is null. It shouldn’t be and i can’t find any mistake here.
Here’s the message we get:

So if anyone would be that kind to give me a hint what to do i would reallly appreciate it.
Ask questions if u don’t understand my way of thinking in code, i will definetely answer.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;



public class TurnScript // : MonoBehaviour
{
    public enum Action // Teoretyczne enum powinien być poza klasą ale wsadziłem go tutaj by inne klasy też mogły go wykorzystać.
    { // Jak wszystkie klasy będą bazować na tym samym enumie to będzie łatwiej to ogarnąć.
        Info,
        Move,
        Guard,
        Attack,
        Throw,
        Pickup,
        Processing
    }

    public ActionInfo AII;
    public ActionMove AM;
    public Weapon AG;
    public Weapon AA;
    public Weapon AT;
    public ActionPickup AP;

    public bool turnTime; //True - kiedy można wykonać ruch, False - wykonywanie akcji

    public void doTurn(Action action, Vector3 position, Vector3 clickpoint1, Vector3 clickPoint2)
    {
        turnTime = false; //Przed odtworzeniem ustawiwamy blokadę przycisków.
        AM.MoveLogic(clickpoint1, position); //Na początku zawsze musi być wykonany jakiś ruch.
        switch (action)
        {
            case Action.Info:
                //Tool Tips, Pause, ext. Nie będziemy tego na tą chwilę rozwijać. Może to kiedyś wykorzystamy choć niesądze.
                //   AII.InfoLogic();
                break;
            case Action.Attack:
                //Damage step, assigning attackers and taking actions.
                AA.AttackLogic();
                break;
            case Action.Guard:
                //Guard from attack and advantages.
                AG.GuardLogic();
                break;
            case Action.Move:
                //Move logic and anything pertaining to movement actions with characters.
                AM.MoveLogic(clickPoint2, clickpoint1);
                break;
            case Action.Throw:
                //Weapon throw, some weapon can't be throw
                AT.ThrowLogic();
                break;
            case Action.Pickup:
                //Interactions with Dropped weapons
                //   AP.PickupLogic();
                break;
            default:
                break;
        }
        turnTime = true; //Po odtworzeniu odblokujemy przyciski
    }
    public bool TurnTime
    {
        get
        {
            return turnTime;
        }

        set
        {
            turnTime = value;
        }
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Character : MonoBehaviour {

    /*
     *  UWAGA !!!!.
     *  Przed wszystkim musimy zwiększyć liczbę zmienntych do zapamiętania. To będzie główny cel tej klasy.
     *  To ta klasa ma zapamiętać stany, siłę, możliwości, wektory poruszania, spadania itp...
     *  Pozostałe klasy mają mieć po prostu funkcje takie na jaki cel wskazuje nazwa tej klasy.
     *  Czyli Charakter ma tobić nam za swoistą bazę danych :)
     *
    */

    public float speed = 5f;
   // Collider character;
    public bool condition = true; // Stan w jakim jest character true(normalny)/false(ogłuszony)
    public bool onTheGround = true; // Niektóre akcje wymagają bycia na ziemi
    private bool isDead; //Tego chyba nie muszę tłumaczyć :smile: ~ M

    public Vector3 clickPoint1;
    public Vector3 clickPoint2;

    TurnScript turn = new TurnScript();
    public TurnScript.Action action = TurnScript.Action.Info; //To jest jak coś obiekt, nie INT. Żeby ktoś nie pomylił z C++;

    //public Transform GroundCheck1; // Put the prefab of the ground here
    //public LayerMask groundLayer; // Insert the layer here.

    void Start()
    {
        turn.turnTime = true;
        //turn = GetComponent<TurnScript>();
        condition = true;
        clickPoint1 = transform.position;
        clickPoint2 = transform.position;
        action = TurnScript.Action.Info;
    }

    void Update()
    {
        if (turn.turnTime) //Sprawdzamy czas i czy możemy coś kliknąć. To ma blokować zmianę akcji podczas wykonywania.
        {
            if (action != TurnScript.Action.Move && Input.GetMouseButtonDown(0))
            {
                clickPoint1 =  Input.mousePosition;
                Debug.Log(clickPoint1);
            }
            checkAction();
            if (action == TurnScript.Action.Move && Input.GetMouseButtonDown(0))
            {
                clickPoint2 = Input.mousePosition;
                Debug.Log(clickPoint2);
            }
            if (Input.GetButtonDown("space"))
            {
                try
                {  
                    turn.doTurn(action, transform.position, clickPoint1, clickPoint2);
                } catch (System.NullReferenceException ex)
                {
                    Debug.Log("Mam dobrą i złą wiadomość. " +
                        "Dobra: try/catch działa fajnie. " +
                        "Zła: WCIĄŻ CZEPIA SIĘ O NULLA");
                    Debug.Log(ex);
                }
            }  
        }
    }

Check the Turn script, line 32 (doTurn method).

And never catch a NullReferenceException, but i think you just did this for debugging purposes…

Yeah i did it for debugging purposes.
I uploaded two same codes accidentaly, fixed now.
I don’t really get it why 32 line in turn script is wrong.

Looks like the AM variable of type ActionMove is null.

1 Like

To catch this kind of error earlier on, do something like this:

private void Awake()
{
  Debug.Assert(AM != null);
  Debug.Assert(AG != null);
  Debug.Assert(AA != null); 
//...etc...
}

And pay attention to your console window. :smile:

1 Like
using System.Collections;
using System.Collections.Generic;
using UnityEngine;



public class TurnScript : MonoBehaviour
{
    public enum Action // Teoretyczne enum powinien być poza klasą ale wsadziłem go tutaj by inne klasy też mogły go wykorzystać.
    { // Jak wszystkie klasy będą bazować na tym samym enumie to będzie łatwiej to ogarnąć.
        Info,
        Move,
        Guard,
        Attack,
        Throw,
        Pickup,
        Processing
    }

    public ActionInfo AII;
    public ActionMove AM;
    public Weapon W;
    public ActionPickup AP;

    public bool turnTime; //True - kiedy można wykonać ruch, False - wykonywanie akcji

    void Awake()
    {
        AM = GetComponent<ActionMove>();
        W = GetComponent<Weapon>();
        Debug.Assert(AM != null);
        Debug.Assert(W != null);
    }

    public void doTurn(Action action, Vector3 position, Vector3 clickpoint1, Vector3 clickPoint2)
    {
        turnTime = false; //Przed odtworzeniem ustawiwamy blokadę przycisków.
        AM.MoveLogic(clickpoint1, position); //Na początku zawsze musi być wykonany jakiś ruch.
        switch (action)
        {
            case Action.Info:
                //Tool Tips, Pause, ext. Nie będziemy tego na tą chwilę rozwijać. Może to kiedyś wykorzystamy choć niesądze.
                //   AII.InfoLogic();
                break;
            case Action.Attack:
                //Damage step, assigning attackers and taking actions.
                W.AttackLogic();
                break;
            case Action.Guard:
                //Guard from attack and advantages.
                W.GuardLogic();
                break;
            case Action.Move:
                //Move logic and anything pertaining to movement actions with characters.
                AM.MoveLogic(clickPoint2, clickpoint1);
                break;
            case Action.Throw:
                //Weapon throw, some weapon can't be throw
                W.ThrowLogic();
                break;
            case Action.Pickup:
                //Interactions with Dropped weapons
                //   AP.PickupLogic();
                break;
            default:
                break;
        }
        turnTime = true; //Po odtworzeniu odblokujemy przyciski
    }

    public bool TurnTime
    {
        get
        {
            return turnTime;
        }

        set
        {
            turnTime = value;
        }
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Character : MonoBehaviour {

    /*
     *  UWAGA !!!!.
     *  Przed wszystkim musimy zwiększyć liczbę zmienntych do zapamiętania. To będzie główny cel tej klasy.
     *  To ta klasa ma zapamiętać stany, siłę, możliwości, wektory poruszania, spadania itp...
     *  Pozostałe klasy mają mieć po prostu funkcje takie na jaki cel wskazuje nazwa tej klasy.
     *  Czyli Charakter ma tobić nam za swoistą bazę danych :)
     *
    */

    public float speed = 5f;
    public bool condition = true; // Stan w jakim jest character true(normalny)/false(ogłuszony)
    public bool onTheGround = true; // Niektóre akcje wymagają bycia na ziemi
    private bool isDead;
    public bool turn;
    public Vector3 clickPoint1;
    public Vector3 clickPoint2;

    public TurnScript turnScript;
    public TurnScript.Action action;
    public ActionInfo AII;
    public ActionMove AM;
    public Weapon W;
    public ActionPickup AP;
    //public Transform GroundCheck1; // Put the prefab of the ground here
    //public LayerMask groundLayer; // Insert the layer here.

    void Start()
    {
        condition = true;
        clickPoint1 = transform.position;
        clickPoint2 = transform.position;
    }
    private void Awake()
    {
        turnScript = GetComponent<TurnScript>();
    }

    void Update()
    {
        if (turnScript.turnTime) //Sprawdzamy czas i czy możemy coś kliknąć. To ma blokować zmianę akcji podczas wykonywania.
        {
            if (action != TurnScript.Action.Move && Input.GetMouseButtonDown(0))
            {
                clickPoint1 = Camera.main.ScreenToWorldPoint(Input.mousePosition);
                Debug.Log(clickPoint1);
            }
            checkAction(action);
            if (action == TurnScript.Action.Move && Input.GetMouseButtonDown(0))
            {
                clickPoint2 = Camera.main.ScreenToWorldPoint(Input.mousePosition);
                Debug.Log(clickPoint2);
            }
            if (Input.GetButtonDown("space"))
            {
             
            }   
        }
    }

    //void checkOnTheGround()
    //{
    //    onTheGround = Physics2D.OverlapCircle(GroundCheck1.position, 0.15f, groundLayer);
    //    // checks if you are within 0.15 position in the Y of the ground
    //}

    void checkAction(TurnScript.Action action) //Nie mamy rozwijanego menu więc tymczasowo przypisałem do klawiszy
    {
        if (Input.GetButtonDown("z"))
        {
            action = TurnScript.Action.Attack;
            Debug.Log("Wybrano atak");
        }
        else if (Input.GetButtonDown("x") && onTheGround) //Blok oczywiście możemy wykonać tylko na ziemi. Tylko nie jestem pewien czy będziemy to sprawdzać w tym miejscu.
        {
            action = TurnScript.Action.Guard;
            Debug.Log("Wybrano obrone");
        }
        else if (Input.GetButtonDown("c") && onTheGround)
        {
            action = TurnScript.Action.Move;
            Debug.Log("Wybrano ruch");
        }

    }
    void checkIsDead()
    {
        if (isDead)
        {
        //    Destroy(character.gameObject);
        }
    }

    public bool IsDead
    {
        get
        {
            return isDead;
        }

        set
        {
            isDead = value;
        }
    }

}

Now i have same problem with turnScript.turntime. It says it’s null but when i try to change value it doesn’t work.
I tried changing value both in TurnScript and in Character. I tried making object in Character and changing it’s value to true or false. None of these work :/.

Sorry, did you mean to say turnScript.turnTime is not null?

no, it says it’s null and i don’t know how to make it = true for example.

Well then if turnScript is null, you won’t be able to access turnTime. You need to assign an instance to turnScript first.

turnScript = GetComponent();
won’t do?

It will - given that there’s a component of that type attached to the object.
If not, you’ll get “null” back. (actually you’ll still get a faked TurnScript in the editor - but it’ll make the null-test evaluate to true).

You can also add one programmatically using ‘AddComponent’. Or you enforce such a component by using the RequireComponentAttribute.

1 Like

Oh so that’s how it works. Thanks, you were really helpful. I don’t have any nulls now.