System Null Reference Exception (card matching game)

I am making a card matching game and i have a System Null Reference Exception which only pops up when I am playing the game and not when I check for errors. I am unsure on how to fix it and would like some help.

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

public class CardControllerScript : MonoBehaviour {

    private Sprite CardBack = null;
    private bool matched;
    public bool check;
    public bool faceUp;
    private CardGame tempGame;

    void Start () {
        matched = false;
}
        void OnMouseDown (){
        if(!faceUp){
           
        gameObject.SetActive (false);
   
            CardGame.count++;
            if (CardGame.CardBack != CardBack.ToString () && CardGame.count == 1){   //Null Reference Exception is for this line
                CardGame.CardBack = CardBack.ToString();
            }else{
                tempGame.CheckWin(CardBack.ToString());
        }
    }
}

    public bool GetMatched(){
    return matched;
}

public bool GetIsFaceUp(){
    return faceUp;
}

public void SeMatchedToTrue(){
    matched = true;
}
       
public void SetCardSprite(Sprite newSprite){
        CardBack = newSprite;
    }

}

If someone could help me fix it that would be greatly appreciated.

here is my other script if it helps

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

public class CardGame : MonoBehaviour {
   
    public static string CardBack = null;
    public static int count = 0;
    private Component[] cards;

    // Use this for initialization
    void Start () {
        CardBack = "";
        cards = this.GetComponentsInChildren<CardGame>();
    }

    // Update is called once per frame
    void Update () {

    }

    public void CheckWin(string secondCard){

        if (count == 2){
            if (CardBack == secondCard){
                Debug.Log ("Matched!");
                count = 0;
                foreach(CardControllerScript card in cards){
                    if(card.ToString() == CardBack){
                        Debug.Log ("you got 1 point");
                        card.SeMatchedToTrue();
                    }
                }
            }else{
                Debug.Log ("Not match!");
                count = 0;
                foreach(CardControllerScript card in cards){
                    if(card.GetMatched() == false){
                        gameObject.SetActive (true);
                    }
                }
            }
        } // if count = 2
    }

}

What is the exact error message (including script and line number)?

I think the issue might be line 14 in CardGame
cards = this.GetComponentsInChildren();
this script is the parent gameobject, looking for all children with the same script, so if grand child will have 0 children under it and the array will be null.
then you’ll get null ref error on line 28 and line 37

if the script CardControllerScript is in each of the children then you could change the variable cards from Component to CardControllerScript
CardControllerScript[ ] cards;
then change the get to
cards = this.GetComponentsInChildren();

that should stop the null ref

line 22 in CardControllerScript is null because you’re calling the script not the variable.
change it to tempGame not CardGame

  • tempGame.count++;
  • if (tempGame.CardBack != tempGame.ToString () && tempGame.count == 1){ //Null Reference Exception is for this line
  • tempGame.CardBack = tempGame.ToString();
  • }else{
  • tempGame.CheckWin(tempGame.ToString());
  • }

edit:
reading this again and again
you are creating a variable called tempGame of type CardGame, but in the If statement you where checking if CardGame.CardBack doesnot = tempGame.ToString(), So now i’m thinking that the .ToString() is an issue. you’re forcing to be a string when it’s not, because it’s a CardGame.
can you give me a Debug.Log(tempGame.ToString()); and tell me what is outputs

oh man and CardBack is static string that is set to null, then in Start() you set it to “”
My second post might not work with this being a static variable.

set it to “” from the beginning.
change
public static string CardBack = null;

to
public static string CardBack = “”;

I did all of your suggestions and now I have 4 errors stating that static member ‘CardGame.count’ cannot be accessed with an instance reference qualify with a type name instead for lines 21-23 with 2 of these for 22. all of the errors are these. I am unsure of how to fix this and I am unsure of how the Debug.log(tempGame.ToString) works and how to check the output. I am new to unity.

i changed the lines below back to CardGame to fix the errors but now the System Null Reference Exception is on line 24 or the line that says }else{. How do i fix this.

  • tempGame.count++;

  • if (tempGame.CardBack

  • tempGame.count

  • tempGame.CardBack

i also reposted the scripts.

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

public class CardControllerScript : MonoBehaviour {

    private Sprite CardBack = null;
    private bool matched;
    public bool check;
    public bool faceUp;
    private CardGame tempGame;

    void Start () {
        matched = false;
}
        void OnMouseDown (){
        if(!gameObject.SetActive (false)){

            CardGame.count++;
            if (CardGame.CardBack != tempGame.ToString () && CardGame.count == 1){
                CardGame.CardBack = tempGame.ToString();
            }else{ //null reference exception is this line
                tempGame.CheckWin(tempGame.ToString());
            }Debug.Log(tempGame.ToString());
    }
}

    public bool GetMatched(){
    return matched;
}

public bool GetIsFaceUp(){
    return faceUp;
}

public void SeMatchedToTrue(){
    matched = true;
}
      
public void SetCardSprite(Sprite newSprite){
        CardBack = newSprite;
    }

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

public class CardGame : MonoBehaviour {
  
    public static string CardBack = "";
    public static int count = 0;
    private Component[] cards;

    // Use this for initialization
    void Start () {
        CardBack = "";
        cards = this.GetComponentsInChildren<CardControllerScript>();
    }

    // Update is called once per frame
    void Update () {

    }

    public void CheckWin(string secondCard){

        if (count == 2){
            if (CardBack == secondCard){
                Debug.Log ("Matched!");
                count = 0;
                foreach(CardControllerScript card in cards){
                    if(card.ToString() == CardBack){
                        Debug.Log ("you got 1 point");
                        card.SeMatchedToTrue();
                    }
                }
            }else{
                Debug.Log ("Not match!");
                count = 0;
                foreach(CardControllerScript card in cards){
                    if(card.GetMatched() == false){
                        gameObject.SetActive (true);
                    }
                }
            }
        } // if count = 2
    }

}

looking into this. check back in a bit. i should have an answer for you

ok, so the main issue is that you have a variable tempGame but it’s null, you have never assigned anything to it.
you created a place to store it when you did “private CardGame tempGame;” but then never put anything in it.

So you’ll need to help me. what is this going to used for? you are trying to check it’s CardBack against the static CardBack.

i’ve fixed most of it, i’m getting a null ref on CardGame now.

here is my code

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

public class CardGame : MonoBehaviour
{

    public static string CardBack = "";
    public static int count = 0;
    private Component[] cards;
    public string cardback;

    // Use this for initialization
    void Start()
    {
        CardBack = "null";
        cards = this.GetComponentsInChildren<CardControllerScript>();
    }

    // Update is called once per frame
    void Update()
    {

    }

    public void CheckWin(string secondCard)
    {

        if (count == 2)
        {
            if (CardBack == secondCard)
            {
                Debug.Log("Matched!");
                count = 0;
                foreach (CardControllerScript card in cards)
                {
                    if (card.ToString() == CardBack)
                    {
                        Debug.Log("you got 1 point");
                        card.SeMatchedToTrue();
                    }
                }
            }
            else
            {
                Debug.Log("Not match!");
                count = 0;
                foreach (CardControllerScript card in cards)
                {
                    if (card.GetMatched() == false)
                    {
                        gameObject.SetActive(true);
                    }
                }
            }
        } // if count = 2
    }

}

and

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

public class CardControllerScript : MonoBehaviour
{

    private Sprite CardBack = null;
    private bool matched;
    public bool check;
    public bool faceUp;
    private CardGame tempGame;

    void Start()
    {
        tempGame = new CardGame(); //creating a new one
        tempGame.cardback = gameObject.name; //seting it's local cardback name
        matched = false;
    }
    void OnMouseDown()
    {
        Debug.Log("Static CardBack : " + CardGame.CardBack);
        Debug.Log("tempgame.cardback : " + tempGame.cardback);
        CardGame.count++;

        if (CardGame.CardBack != tempGame.cardback && CardGame.count == 1)
        {
            //not the same
            Debug.Log("Not the same");
            CardGame.CardBack = tempGame.cardback;
        }
        else
        {
            // same, so it's a match
            Debug.Log("Match found");
            tempGame.CheckWin(tempGame.cardback);
        }

         
     
    }

    public bool GetMatched()
    {
        return matched;
    }

    public bool GetIsFaceUp()
    {
        return faceUp;
    }

    public void SeMatchedToTrue()
    {
        matched = true;
    }

    public void SetCardSprite(Sprite newSprite)
    {
        CardBack = newSprite;
    }

}

sorry i missed this line in my script:
Code (CSharp):

I changed it to your code and added the line i missed out and now the system null reference exception is for line 24 which is CardGame.count++;
EDIT: just realised you already said that.

i’m still working on it. give me a few more mins

sure that is fine take as long as you need. Thanks for all the help by the way.

All my error are removed, So I used the Card name to get matches, so like card1, card2, card3. I have 2 of each of them in my scene.
You can remove my Debug, they are just there to help me follow the code.
just a recap, My parent gameobject has the CardGame script attached to it. each card has the CardControllerScript attached to it.
and each card is a subobject of the parent

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

public class CardGame : MonoBehaviour
{

    public static string CardBack = "null";
    public static int count = 0;
    private CardControllerScript[] cards;
    public string cardback;

    // Use this for initialization
    void Start()
    {
        CardBack = "null";
        cards = this.GetComponentsInChildren<CardControllerScript>();
        Debug.Log(cards.Length);
    }

    // Update is called once per frame
    void Update()
    {

    }

    public void CheckWin(string secondCard)
    {
        Debug.Log("CheckWin : " + CardBack + " : " + secondCard);
        if (count == 2)
        {
            if (CardBack == secondCard)
            {
                Debug.Log("Matched!");
                count = 0;
                for (int i = 0; i < cards.Length; i++)
                {
                  
                    if (cards[i].getCardBack() == secondCard)
                    {
                        Debug.Log("SeMatchedToTrue");
                        cards[i].SeMatchedToTrue();
                    }
                  
                }
                Debug.Log("you got 1 point");
            }
            else
            {
                Debug.Log("Not match!" + cards.Length);
                count = 0;
                for (int i = 0; i < cards.Length; i++)
                {
                  
                    if (cards[i].GetMatched() == false)
                    {
                        cards[i].gameObject.SetActive(true);
                    }
                    CardBack = "null";
                }
            }
        } // if count = 2
    }

}

and

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

public class CardControllerScript : MonoBehaviour
{

    private Sprite CardBack = null;
    private bool matched;
    public bool check;
    public bool faceUp;
    private CardGame tempGame;

    void Start()
    {
        //tempGame = new CardGame(); //creating a new one
        tempGame = gameObject.GetComponentInParent<CardGame>();
        tempGame.cardback = gameObject.name; //seting it's local cardback name
        matched = false;
    }
    void OnMouseDown()
    {
        Debug.Log("Static CardBack : " + CardGame.CardBack);
        Debug.Log("cardback : " + gameObject.name);
        CardGame.count++;

        Debug.Log("count = " + CardGame.count);
        if (CardGame.count == 1)
        {
            //not the same
            Debug.Log("not 2 picked");
            CardGame.CardBack = gameObject.name;
        }
        else
        {
            // Check if they are the same
            Debug.Log("check if same");
            tempGame.CheckWin(gameObject.name);
        }

          
      
    }

    public bool GetMatched()
    {
        return matched;
    }

    public bool GetIsFaceUp()
    {
        return faceUp;
    }

    public void SeMatchedToTrue()
    {
        matched = true;
    }

    public void SetCardSprite(Sprite newSprite)
    {
        CardBack = newSprite;
    }

    public string getCardBack()
    {
        return gameObject.name;
    }
}

you still have some logic to clean up. swapping out the sprite, enabling or disabling the card when it has been matched. stopping the playing from clicking on the same card

so the cards that matched have to be named the same or not

yes, they need to be named the same.
or you have to create a public string and check everything based on that string

ok thanks, where you would put the enabling and disabling of the cards in the script. i would imagine that the disabling would be after the on mouse down command and the enabling would be in the not match section.

so if the card was two cards named cardback that would work and two cards named cardback(1) and so on