Панель автоматического скрытия Unity

Я создаю приложение AR, используя Unity.

Он имеет сцены входа/регистрации, которые позволяют пользователю войти или зарегистрироваться в приложении.

Для обработки ошибок и отображения сообщений об ошибках для пользователя (например, неверный адрес электронной почты) я просто создаю панель с текстом на ней для отображения сообщений об ошибках. На этой панели также есть кнопка, чтобы закрыть сообщение и снова скрыть панель ошибок.

Эта панель накладывается поверх основной панели пользовательского интерфейса, на которой есть поля ввода.

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

Но я не могу установить состояние этой панели на Awake(). Я продолжаю получать сообщение об ошибке NullReferenceException: ссылка на объект не указывает на экземпляр объекта.

Я установил скрипт на панель ошибок и добавил объект Panel в скрипт в Инспекторе. изображение прикреплено для справки.

Ниже приведен мой сокращенный код (using опущено для краткости). Я пытался установить его в Start() и Awake(), но оба выдают одну и ту же ошибку. Если я устанавливаю errorPanel.gameObject.SetActive(true); в Awake(), ошибка не возникает. Он генерируется, только если для него задано значение false.

public class RegisterScene : MonoBehaviour {
    public GameObject errorPanel; // Error panel

    void Awake()
    {
        errorPanel = GameObject.FindGameObjectWithTag("errorPanel"); // Error panel Tag
        Debug.Log("Error Panel: " + errorPanel); // Outputs "ErrorPanel" as named in Inspector
        errorPanel.gameObject.SetActive(false); // Have to hide on scene Awake - throws NullReferenceError here
        //errorPanel.gameObject.SetActive(true); // This works as a test case
    }

    // Register button clicked
    public void Register ()
    {
        // If error 
        showErrorPanel("You must complete all sections");
    }

    // Show error panel
    public void showErrorPanel(string errorMessage)
    {
        Debug.Log("Showing error panel");
        errorPanel.gameObject.SetActive(true); // Working - shows error panel

        // Confirmation button on error panel clicked
        hideErrorPanel();
    }

    // Hide error panel
    public void hideErrorPanel()
    {
        Debug.Log("Hiding error panel");
        errorPanel.gameObject.SetActive(false); // Working - hides error panel
    }
}

введите здесь описание изображения


person heyred    schedule 11.06.2018    source источник
comment
Порядок вызова Awake() для каждого объекта отсутствует. (Если вы не укажете порядок сценариев, и это просто обман). Таким образом, ваш RegisterScene активируется раньше, чем ваш errorPanel. Эмпирическое правило: получайте ссылки в Awake и выполняйте действия в Start. Если по какой-то причине вам нужно сделать это в Awake, вы должны сначала проверить NULL на errorPanel. Затем позвольте errorPanel установить состояние по умолчанию как неактивное.   -  person jiveturkey    schedule 11.06.2018
comment
Сценарий RegisterScene в вашем вопросе отличается от того, который прикреплен к вашему GameObject. Вы удалили так много кода, и я думаю, что проблема может исходить оттуда. Обязательно сохраните скрипт, запустите его еще раз из редактора, затем дважды щелкните ошибку. Он приведет вас туда, где ошибка. Убедитесь, что это именно то место, откуда, как вы сказали, исходит ошибка.   -  person Programmer    schedule 11.06.2018
comment
Я не уверен, что следую @jiveturkey. Я перетащил свой скрипт C# RegisterScene в свою панель ошибок в иерархии. Затем я перетащил эту панель на GameObject в Инспекторе. Не означает ли это, что мой код будет вызываться в Awake, даже если все мои элементы используют один и тот же сценарий RegisterScene?   -  person heyred    schedule 11.06.2018
comment
@Programmer Yip Я сделал это, и весь код, который я пропустил, не имел отношения к вопросу. Ранее я дважды щелкнул ошибку, и она привела меня к строке, которую я отметил в приведенном выше коде, где возникает ошибка.   -  person heyred    schedule 11.06.2018
comment
Прошу прощения, фотку не увидел. Спасибо за объяснение. Один вопрос, есть ли еще ErrorPanel'ы? Вероятно, вам следует вызывать GetComponentInChildren‹›   -  person jiveturkey    schedule 11.06.2018
comment
@jiveturkey нет других наборов ErrorPanels. В качестве теста я создал тестовую панель, и она выдала ту же ошибку.   -  person heyred    schedule 11.06.2018
comment
См. Ответ @Programmer ниже   -  person jiveturkey    schedule 11.06.2018


Ответы (1)


Если я устанавливаю errorPanel.gameObject.SetActive(true); в Awake() - ошибка не возникает. Он выбрасывается только тогда, когда для него установлено значение false.

Вот, вероятно, что происходит:

Ваш скрипт RegisterScene прикреплен к другому игровому объекту. При вызове GameObject.FindGameObjectWithTag("errorPanel") ваша панель возвращается. Когда вы устанавливаете его на false с помощью errorPanel.gameObject.SetActive(false), он деактивирует его.

Затем функция Awake будет вызываться для другого игрового объекта, к которому она прикреплена, который также вызовет GameObject.FindGameObjectWithTag("errorPanel"), но на этот раз вернет null. Он вернет null, потому что функции GameObject.FindXXX не могут найти деактивированные объекты. Поскольку это null, вызов errorPanel.gameObject.SetActive вызовет это исключение.

У вас есть два варианта:

1. Найдите и удалите скрипт из другого игрового объекта:

введите здесь описание изображения

2. Используйте мою функцию FindInActiveObjectByTag, чтобы найти деактивированные игровые объекты, если вам нужно найти неактивные игровые объекты. .

person Programmer    schedule 11.06.2018