0
\$\begingroup\$

I have a script that is attached to all the NPCs in my game.

Here's what the variable declarations and Awake() function look like:

Dialogue dialogue;
TextMeshProUGUI UIText;
GameObject textBox;
Image portrait;
AudioSource audioSource;

private void Awake()
{
    audioSource = GameObject.Find("Audio Source").GetComponent<AudioSource>();
    UIText = GameObject.Find("Canvas").GetComponentInChildren<TextMeshProUGUI>();
    textBox = GameObject.Find("TextBox");
    portrait = GameObject.Find("Portrait").GetComponent<Image>();

    textBox.SetActive(false);
}

All of this works fine, until it gets to

portrait = GameObject.Find("Portrait").GetComponent<Image>();

For some reason, it throws a NullReferenceException on that line.

Two things about this confuse me:

  • The GetComponents above (for the audioSource and UIText) appear to work fine, despite being called for each of the NPCs. I'd assume it'd either work for all or none of them.

  • The portrait variable is used to show a portrait of the NPC when the player is talking to them, and even with the errors, one of the NPCs still has their portrait. It's like one NPC grabs the Image component, and none of the others can snag it or something...?

Anyway, very grateful for any wisdom y'all may provide, and happy to provide any other info that could lead to a resolution. Thanks! Hope your new year is going well!

EDIT: There is a Portrait GameObject in my scene under the Canvas, with an Image component attached to it. This I can confirm.

\$\endgroup\$

1 Answer 1

0
\$\begingroup\$
portrait = GameObject.Find("Portrait").GetComponent<Image>();

There is exactly one way for this line to throw a null reference exception, and that is if no game object named "Portrait" was found in your scene at the time this script ran.

Things to check:

  • Does the "Portrait" object or anything in its parent chain get spawned dynamically at runtime? If so, it might not be in the scene by the time your NPC script gets its Awake() message.

    You can try delaying this initialization to Start() or a manual initialization routine, or change the order you spawn content to ensure the portrait has fully loaded before the NPC goes looking for it.

  • Does the spelling of your "Portrait" game object's name differ in any tiny detail from the string you're looking for? Double-check capitalization, or leading/trailing whitespace. To be extra-sure, paste both strings into a Unicode character checker to reveal any non-printing characters. And note that if the portrait is spawned dynamically, it might get the string " (copy)" automatically appended to its name during instantiation.

    (This minefield is the risk we run with stringly-typed code, and one reason why it's often recommended to avoid looking up objects by name)

If these assets are often requested by various NPCs or other scripts, it might make more sense to expose them via a Service Locator, eg...

public class DialogueSystem : MonoBehaviour {
    public AudioSource audio;
    public Image portrait;
    public GameObject textBox;
    public TextMeshProGUI uiText;

    static DialogSystem _instance;
    public static DialogueSystem instance {
        get {
            return _instance;
        }
    }

    public void Awake() {
        if(_instance != null)
            Debug.LogError("You somehow have two dialogue systems in your scene at once");
        _instance = this;
    }
}

You can set this up as part of the same structure/prefab that holds your portrait and the like, and wire up the references in advance.

Then, instead of searching your whole scene for named objects four times every time you spawn an NPC, you can instead just ask the DialogueSystem whenever you want to show some dialogue:

DialogueSystem.instance.portrait.sprite = foo;
\$\endgroup\$
1
  • \$\begingroup\$ WOW! GREGORY! This Service Locator class is so clean, and works beautifully! Thank you so much! \$\endgroup\$
    – Casey
    Jan 5, 2019 at 17:46

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .