Синхронизация инициализации объекта Unity - PullRequest
0 голосов
/ 28 июня 2019

До сих пор я думал, что функции в monobehaviour будут выполняться в следующем порядке:

OnEnable> Пуск> Обновление> OnDisable

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

  1. Итак, первый вопрос: это правда?Будет ли update НЕ выполняться, пока не закончится start?

Тогда у меня возникнет проблема с синхронизацией между различными monobehaviour классами.

У меня есть класс, который создает некоторые объекты (Меню в основном) в его start функции.Тогда в другом классе у меня есть подобный код, но он также зависит от объекта, созданного первым классом, который уже существует.Я получаю сообщение об ошибке, потому что объект еще не найден.

NullReferenceException: ссылка на объект не установлена ​​на экземпляр объекта ShopHandler.Start () (в Assets / Scripts / Shops / ShopHandler.cs: 60)

Так что теперь я застрял с этим.Поэтому мой второй вопрос будет

Как мне синхронизировать мои разные классы, когда они зависят от других, подобных этому ?

Наконец, вопрос, смешанный с этими двумя, также должен быть задан:

Будет ли функция update выполняться в любом из этих классов, пока они как-то "ждут" своей части инициализации, будь то функция start, функция OnEnable или что-то еще?

Конечно, функция update полагается на объекты, которые уже инициализируются, и это может привести к новым проблемам.

Заранее спасибо

Ответы [ 3 ]

2 голосов
/ 28 июня 2019

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

Итак, первый вопрос: это правда? Обновление НЕ будет выполнено, пока не закончится начало?

Обычно да, но есть исключение.

Если вы реализуете Start в качестве сопрограммы, Update можно вызвать до того, как Start завершится в том же монобахе.

Например, этот код:

IEnumerator Start() 
{
    Debug.Log("Start beginning");

    yield return null;

    Debug.Log("Start continuing");

    yield return null;

    Debug.Log("Start completing");    
}

void Update() 
{
    Debug.Log("Update running");
}  

Может выдать этот вывод:

Начало начала
Начать продолжение
Обновление работает
Начните заполнять
Обновление работает
Обновление работает
Обновление работает
...

1 голос
/ 01 июля 2019

Вот мой подход:

Допустим, у вас есть два монобихи поведения A и B. Предположим, что B должен инициализироваться после A. Затем;

1-) Создайте функцию, то есть «Инициализируйте» и используйте ее в B вместо функции Start:

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

public class B : MonoBehaviour
{

    public void Initialise()
    {
        //Code you run on Start()    
    }

}

2-) Ссылка B obj в A obj, используйте bObj.Initialise после того, как готовы его инициализировать:

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

public class A : MonoBehaviour
{
    public B bObj;
    // Start is called before the first frame update
    void Start()
    {
        //Things to do in Start()
        //...
        //...
        //...
        bObj.Initialise();
    }

}

Наконец, если вы хотите, чтобы ваша функция обновления запускалась когда угодно, я обычно предпочитаю использовать что-то в качестве флага. Итак, вот моя вторая версия класса B для управления поведением update ():

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

public class B : MonoBehaviour
{
    public bool canUpdate;
    public void Initialise()
    {
        //Code you run on Start()
        canUpdate = true;    
    }
    private void Update()
    {
        if (canUpdate)
        {
            //do the stuff
        }
    }

}
0 голосов
/ 28 июня 2019

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

  1. Да, все функции запуска (и пробуждения) вызываются до функции обновления, , если игровые объекты / монобихи активированы / активны! Start / Awake / Update не вызываются на неактивных игровых объектах

  2. Вы должны посмотреть на Script Execution Order. Здесь вы можете убедиться, что функции запуска / пробуждения / обновления классов вызываются в определенном порядке. Он должен быть указан в настройках проекта.

  3. При инициализации сцены будет вызвано обновление после завершения всех функций пробуждения / запуска (если только они не определены как сопрограммы, но это, вероятно, не ваша проблема).

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