C# Unity Queue NullReferenceException - PullRequest
0 голосов
/ 13 марта 2020

Я пытаюсь создать простую диалоговую систему для моей игры в Unity. Я установил специальный триггер для запуска диалога, и код передает правильную переменную, но каким-то образом он застревает при очистке очереди и выдает NullReferenceException.

Я видел через отладчик, что все переменные и триггеры прекрасно работали до cs: 27 внутри DialogueManager.cs. Я также проверил инспектора, чтобы убедиться, что все правильно назначено.

Диалог класс:

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

[System.Serializable]
public class Dialogue
{
    public string name;

    [TextArea(3,10)]
     public string[] sentences;
}

DialogueTrigger класс:

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

public class NPC_DialogTrigger : MonoBehaviour
{
    // Player
    public Transform player;

    // GameMaager to close
    public GameObject Gameplay;

    // Camera and Canvas to turn on
    public GameObject DialogueManager;

    // NPC Details
    public GameObject InteractionNPCNameTextField;
    public Transform interactionTransform;
    public float radius = 3f;
    private bool isBusy = false;

    // DialogueStart
    public GameObject DialogueStart;

    void Start()
    {
        InteractionNPCNameTextField.gameObject.SetActive(false);
    }

    void Update()
    {
         float distance = Vector3.Distance(player.position, interactionTransform.position);

         if (distance <= radius)
         {
              if (isBusy == false)
              {
                   InteractionNPCNameTextField.gameObject.SetActive(true);

                   if (Input.GetKeyDown(KeyCode.E))
                   {
                        Dialogue();
                        Debug.Log("Started Dialogue procedure.");
                   }
              }
         }
         else if (distance > radius)
         {
             InteractionNPCNameTextField.gameObject.SetActive(false);
         }
    }

    public void Dialogue()
    {
        Gameplay.SetActive(false);
        DialogueManager.SetActive(true);
        DialogueStart.GetComponent<DialogueStart>().TriggerDialogue();
        Debug.Log("Triggered Dialogue.");
    }

    void OnDrawGizmosSelected()
    {
        if (interactionTransform == null)
        {
            interactionTransform = transform;
        }

        Gizmos.color = Color.yellow;
        Gizmos.DrawWireSphere(interactionTransform.position, radius);
    }
}

DialogueStart класс:

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

public class DialogueStart : MonoBehaviour
{
    public Dialogue dialogue;

    public void TriggerDialogue()
    {
        FindObjectOfType<DialogueManager>().StartDialogue(dialogue);
         Debug.Log("Dialogue sent to dialogue manager.");
    }
}

DialogueManager класс:

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

public class DialogueManager : MonoBehaviour
{
    public Text nameText;
    public Text DialogueText;

    private Queue<string> sentences;
    public GameObject DialogueManagerUI;

    void Start()
    {
        if (sentences == null)
        {
             sentences = new Queue<string>();
        }
    }

    public void StartDialogue (Dialogue dialogue)
    {
        Debug.Log("Received dialogues: " + dialogue);
        nameText.text = dialogue.name;
        Debug.Log("Start Dialogue: " + sentences.Count);
        sentences.Clear();
        Debug.Log("Sentences Cleared: " + sentences);

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

        DisplayNextSentence();
    }

    public void DisplayNextSentence()
    {
        if(sentences.Count == 0)
        {
            EndDialogue();
            return;
        }

        string sentence = sentences.Dequeue();
        DialogueText.text = sentence;
    }

    void EndDialogue()
    {
        Debug.Log("End of conversation.");
    }

    private void Update()
    {
        if (DialogueManagerUI.activeInHierarchy)
        {
            Cursor.lockState = CursorLockMode.None;
            Cursor.visible = true;
        }
        else if (!DialogueManagerUI.activeInHierarchy)
        {
            Cursor.lockState = CursorLockMode.Locked;
            Cursor.visible = false;
        }
    }
}

Visual Studio не дает мне любые ошибки.

Код ошибки Unity -> Снимок экрана

Отладчик непосредственно перед выпуском -> Снимок экрана2

Мне кажется, что очередь никогда не присваивается предложениям и остается пустым. Если это так - почему?

1 Ответ

3 голосов
/ 13 марта 2020

Звучит так, как будто DialogueManager.StartDialogue, вероятно, через DialogueStart.TriggerDialogue вызывается откуда-то из Awake или, по крайней мере, до того, как ваш Start был выполнен.

Особенно

DialogueManager.SetActive(true);

давайте предположим, что объект DialogueManager сначала неактивен. Поэтому, возможно, ваш материал вызывается до того, как он становится активным.

Это также может быть связано с Start, где вы устанавливаете

InteractionNPCNameTextField.gameObject.SetActive(false);

, поэтому любой компонент на этом GameObject может не вызывается метод Start. Может быть, вы указали неправильный GameObject здесь?

Отладка поможет выяснить, в каком порядке будут вызываться ваши методы.

В общем, мое правило большого пальца для инициализации:

  • Делайте все, что зависит только от вас самих, в Awake
  • Делайте все, что зависит от настроек других компонентов, уже в Start

Это Таким образом, вы можете (почти) всегда быть уверены, что материал уже инициализирован, когда вам это нужно.


Однако это только догадки, но

Простое решение здесь:

Вы уже могли решить эту проблему, просто инициализировав sentences сразу, используя

private readonly Queue<string> sentences = new Queue<string>();

, теперь он определенно инициализируется даже до того, как Start или Awake будут вызваны!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...