Unity: NullReferenceException: ссылка на объект не установлена ​​для экземпляра объекта с несколькими операторами gameObject.SetActive

Я столкнулся с этой ошибкой при попытке скрыть игровой объект, это панель. Панель содержит холст и две кнопки.

Изначально панель скрыта и скрипт работает. Ошибка возникает, когда я пытаюсь снова включить panel.SetActive(true) и вернуться к панели.SetActive(false).

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

public class EquipmentSlot : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IPointerDownHandler, IPointerUpHandler
{
    public GameObject panel;

    void Start()
    {
       GameObject panel= GameObject.FindGameObjectWithTag("panel");
    }

    public void OnPointerEnter(PointerEventData eventData)
    {
        GameObject panel= GameObject.FindGameObjectWithTag("panel");
        panel.SetActive(false);
    }

    public void OnPointerExit(PointerEventData eventData)
    {
        GameObject panel = GameObject.FindGameObjectWithTag("panel");
        panel.SetActive(true);
    }
}

Я удалил любой ненужный код. Я хотел бы, чтобы панель открывалась и закрывалась при наведении курсора на элемент меню, и чтобы вы знали, функции наведения работают в моем коде.

1 ответ

Эта проблема

FindGameObjectWithTag который afaik равен GameObject.FindWithTag в новых версиях не находит объекты, которые неактивны!

Возвращает один активный GameObject помеченный тег Возвращает null если нет GameObject был найден.

Так что после установки его SetActive(false) вы не найдете его снова, используя любой из Find вариации.

Кроме того, вы создаете новую локальную переменную под названием panel каждый раз скрывая уже существующее panel вместо того, чтобы использовать тот, который у вас уже есть.

Решение

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

public class EquipmentSlot : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler/*, IPointerDownHandler, IPointerUpHandler*/
{
    // if you referenced this in the Inspector e.g. via drag & drop
    // you could completely skip the Find in the start method
    public GameObject panel;

    void Start()
    {
       panel = GameObject.FindGameObjectWithTag("panel");
    }

    public void OnPointerEnter(PointerEventData eventData)
    {
        panel.SetActive(false);
    }

    public void OnPointerExit(PointerEventData eventData)
    {
        panel.SetActive(true);
    }
}

(Конечно, если объект был уничтожен, это все равно даст вам исключение.)

Другие вопросы по тегам