0
\$\begingroup\$

I have 3 NPCs in my "Game". When the player walks up to any of them, they're supposed to have their own dialogue; I've tested this, and they do.

I tried to create a display that shows this dialogue text using a TextMeshProUGUI attached to a blank GameObject called dialogDisplay (tagged DialogDisplay). There is one DialogDisplay object in the scene that I'm trying to get each of my NPC's to use. I tried to make the display object inactive in the NPC Start() function, and enable it when it's time to display the NPC's next sentence.

When I run my game, I get an error on line 21, where SetActive() is called: "Object Reference Not Set to an Instance of an Object".

Here's the NPC script (DisplayNextSentence() is at the bottom, where dialogDisplay is used):

public class NPC : Character {
private bool charInRange;
public Dialogue dialogue;
public bool talkedTo = false;
private Queue<string> sentences;
public TextMeshProUGUI textPro;
public GameObject dialogDisplay;
private bool isTalking;

// Use this for initialization
void Start () {
    charInRange = false;
    textPro = FindObjectOfType<TextMeshProUGUI>();
    dialogDisplay = GameObject.FindGameObjectWithTag("DialogDisplay");
    dialogDisplay.SetActive(false);
}

// Update is called once per frame
void Update () {
    //if player is in range and presses space, triggers NPC dialogue
    if (charInRange && Input.GetKeyDown(KeyCode.Space))
    {
        TriggerDialogue();
    }
}

//if Player gameObject is in NPC collider, player is in range
void OnTriggerEnter2D(Collider2D other)
{
    if(other.gameObject.tag == "Player")
    {
        charInRange = true;
    }
}

//if player exits NPC collider, player is not in range
void OnTriggerExit2D(Collider2D other)
{
    if (other.gameObject.tag == "Player")
    {
        charInRange = false;
    }
}

//if NPC has been talked to before, displays next sentence; if not, loads dialogue and displays first sentence
private void TriggerDialogue()
{
    if (!talkedTo)
    {
        talkedTo = true;
        StartDialogue(dialogue);
    }
    else
    {
        DisplayNextSentence();
    }
}

//loads a queue with lines from Dialogue and displays first sentence
public void StartDialogue(Dialogue dialogue)
{
    sentences = new Queue<string>();

    foreach (string sentence in dialogue.sentences)
    {
        sentences.Enqueue(sentence);
    }

    DisplayNextSentence();
}

//displays next sentence in the queue
public void DisplayNextSentence()
{
    string sentence;
    bool done = false;

    //if last sentence in the queue, display it again
    if (sentences.Count == 1)
    {
        sentence = sentences.Peek();
        textPro.text = sentence;
        Debug.Log(sentence);
        return;
    }

    sentence = sentences.Dequeue();
    textPro.text = sentence;
    dialogDisplay.SetActive(true);
    while (!done) {
        Debug.Log("In WHile Looop");
        if (Input.GetKeyDown(KeyCode.A))
        {
            done = true;
        }
    }
    dialogDisplay.SetActive(false);
}
}

Grateful for any insight or tips you can provide. Happy to provide further information if it helps. Thank you!

\$\endgroup\$
1
\$\begingroup\$

"Object Reference Not Set to an Instance of an Object" occurs when whatever Object you're trying to use doesn't actually contain anything.

It is most likely coming from dialogDisplay = GameObject.FindGameObjectWithTag("DialogDisplay");, check to see if the GameObject in the scene has that tag attached to it.

\$\endgroup\$
  • \$\begingroup\$ Thanks NiceRookie. That's what I thought too; however, the DialogDisplay object does have the tag "DialogDisplay" on it. \$\endgroup\$ – Casey Dec 18 '18 at 2:12
  • \$\begingroup\$ @Casey I think this is the correct answer, if you try to do Debug.Log(dialogDisplay) before the error line, you will most likely see it being null, so when you execute its SetActive method, it produces this error. \$\endgroup\$ – TomTsagk Dec 18 '18 at 10:02
  • \$\begingroup\$ Thanks @TomTsagk. You’re probably right (I will check today), but how do I make it so that it’s not null? It shouldn’t be null, since I’m assigning the variable to the existing, tagged DialogDisplay in the scene. \$\endgroup\$ – Casey Dec 18 '18 at 12:44
  • \$\begingroup\$ @Casey Make sure you are not calling the function the wrong way, or even better, you could put public GameObject dialogDisplay; and attach it from the inspector, thus ensuring it will never be null, unless the object itself is destroyed. \$\endgroup\$ – TomTsagk Dec 18 '18 at 12:57

Not the answer you're looking for? Browse other questions tagged or ask your own question.