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
}
}
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();
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;
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.
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 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.
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
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.