0

I'm having a problem changing the scoring values using TextMeshPro in a canvas from a script within the canvas. I'm getting a NullPointerException error because i feel that i am not referencing the score text files correctly but im not sure how to do it correclty. Error :

NullReferenceException: Object reference not set to an instance of an object Score.PlayerOneScored () (at Assets/Scripts/Score.cs:20)

Code :

public class Score : MonoBehaviour
{
static int scoreValue1 = 0;
static int scoreValue2 = 0;
private TMP_Text score1;
private TMP_Text score2;

public void PlayerOneScored() {
    Debug.Log("Player One Scored");
    scoreValue1++;

    TMP_Text score1 = GetComponent<TextMeshProUGUI>();
    Debug.Log("P1 Score: " + scoreValue1);
    score1.text = "Score: " + scoreValue1;
    }

public void PlayerTwoScored()
{
    Debug.Log("Player Two Scored");
    scoreValue2++;

    TMP_Text score2 = GetComponent<TMP_Text>();
    Debug.Log("P2 Score: " + scoreValue2);
    score2.text = "Score: " + scoreValue2;
    }
}

Line 20 is

score1.text = "Score: " + scoreValue1;

Picture of the Hierarchy : ScoreCanvas

Update Have it working now! This was my class in the end

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

   public class Score : MonoBehaviour
   {
   static int scoreValue1 = 0;
   static int scoreValue2 = 0;
   public TextMeshProUGUI score1;
   public TextMeshProUGUI score2;


void Awake()
{
    score1.text = "Score: " + scoreValue1;
    score2.text = "Score: " + scoreValue2;
}


public void PlayerOneScored() {

    if (scoreValue1 < 10) {
        scoreValue1++;
        Debug.Log("Player One Scored");
        Debug.Log("P1 Score: " + scoreValue1);

        score1.text = "Score: " + scoreValue1;
    }
    else { }
}

public void PlayerTwoScored()
{
    if (scoreValue2 < 10)
    {
        scoreValue2++;
        Debug.Log("Player Two Scored");
        Debug.Log("P2 Score: " + scoreValue2);

        score2.text = "Score: " + scoreValue2;
    }
    else { }
}
}
ConnnK
  • 19
  • 1
  • 7
  • I doubt that actually .. I'ld go with Draco18s: The `score1` is `null` since `GetComponent` fails .. are you sure this script is on the correct GameObject, the same which also has a `TextMeshProUGui` component? There is nothing else in that method which can possibly throw this exception .. which could easily see by debugging with breakpoints so I'ld say it is a duplicate. In the other one you are also using `TMP_Text` .. maybe you should use it in the first one as well? – derHugo Nov 21 '19 at 20:07
  • 1
    If this is no duplicate in your opinion please argue what exactly you tried / didn't understand from the duplicate thread. – derHugo Nov 21 '19 at 20:09
  • @derHugo The Score script is attached to the ScoreCanvas, where both the Text files are attached. I read through the link and many other pages and i cannot understand in my case what i'm doing wrong, i'm a begineer at unity and have a heavy workload with other subjects so i wanted to ask you hoping ye wouldnt shut my thread down again because i cant understand what i'm doing wrong. The duplicate thread is very very broad and i can't find where it can help me. I'm dumb basically. Thats why i wanted help – ConnnK Nov 21 '19 at 21:16

1 Answers1

1

In the comment you said your script is attached to the Canvas GameObject.

But you are using

GetComponent<TextMeshProUGui>();

Note that GetComponent

Returns the component of Type type if the game object has one attached, null if it doesn't.

It only returns Components attached to the very same GameObject. In your description this is not the case. The Components you are trying to get are on child GameObjects of your Canvas!


Now if there would be only one you could use another variant like GetComponentInChildren ... BUT: since in your case you have two different ones and want to be able to differ between them you can't use it .. it would always return the same reference.


There are multiple possible solutions but here is what I would do: Simply remove both GetComponent lines completely and rather set your references via the Unity Inspector! This can be done by either make a field public or use [SerializeField] on a private one:

// Now both these fields will appear in the Inspector
// so you can simply drag&drop the according GameObjects into the slots
[SerializeField] private TextMeshProUGUI score1;
public TextMeshProUGUI score2;

Another option would be to get the according child objects on runtime (this is more error prone ofcourse)

score1 = transform.GetChild(0).GetComponemt<TextMeshProUGUI>();

...

score2 = transform.GetChild(1). GetComponent<TextMeshProUGUI>();
derHugo
  • 49,310
  • 9
  • 37
  • 73
  • Thanks so much! So i changed that to public and assigned it (i had tried this before but now i see i was overriding it with the GetComponent so i deleted that). My only problem now is that fact that for my game, the scene resets each time a player scores, therefore reseting the text (but not the values of score). So i see that the score has changed and then it immediately changes back to the deafult value. How would i go about keeping the written string across the reset for the scene? – ConnnK Nov 22 '19 at 11:37
  • Never mind, got it working. Will put in update what i did. Thank you! – ConnnK Nov 22 '19 at 12:35