Приложение / игра полностью зависает при запуске сопрограммы - PullRequest
0 голосов
/ 28 апреля 2018

Мое приложение / игра для Android ARCore Unity зависает при запуске сопрограммы, а затем возобновляется после ее завершения. Сопрограмма находится в сценарии, прикрепленном к игровому объекту, и сопрограмма вызывается в функции Start (). Я попытался вставить yield return null; в большее количество частей сопрограммы, что сокращает время пауз, но добавляет больше пауз, что приводит к очень прерывистому (в основном несуществующему) игровому процессу на секунду или две после создания экземпляра объекта. Может ли это произойти, потому что ARCore не поддерживает многопоточный рендеринг? Если это так (или нет), как я могу это исправить, чтобы моя сопрограмма работала (я полагаю, «в фоновом режиме») после создания объекта, и поэтому он не влияет на FPS игрового процесса?

Вот мой код:

void Start() 
{
    StartCoroutine(MyCoroutine());
}

IEnumerator MyCoroutine ()
{
    yield return null;
    Transform[] allChildren = GetComponentsInChildren<Transform>();
    foreach (Transform child in allChildren)
    {
        if (child.gameObject.GetComponent<MeshFilter>())
        {
            if (!child.gameObject.GetComponent<MeshCollider>())
            {
                child.gameObject.AddComponent<MeshCollider>();
            }
        }
        child.gameObject.tag = "CenterObject";
    }
}

Ответы [ 3 ]

0 голосов
/ 28 апреля 2018

У сопрограмм, кажется, есть издержки при их создании, как обсуждалось здесь: https://forum.unity.com/threads/startcoroutine-performance-cost.233623/

Учитывая, что вы создаете экземпляры объектов, я бы предложил следующие пути:

  • Измените сопрограмму на простой вызов функции, поскольку вам, кажется, не требуется никакой задержки между итерациями цикла, что является основной идеей использования сопрограммы в Unity. Вы также добавляете коллайдеры и ожидаете продолжения игрового процесса, что может вызвать неожиданное поведение, если вам нужно зарегистрировать столкновения.
  • Создание префабов, к которым заранее прикреплены коллайдеры, если это возможно.
  • Используйте пул объектов, в котором вы будете создавать объекты до начала игрового процесса, активируйте их при необходимости и отключайте их, когда они уничтожаются, при необходимости.
0 голосов
/ 30 апреля 2018

В дополнение к ответам, фиксирующим ваш сопрограмм:

Сопрограммы на самом деле не многопоточны! Вот почему ваше приложение зависает, если в сопрограмме есть длинная задача.

* * * * yield return сопрограмм просто делает / ленивым сделать быструю анимацию или что-то подобное, потому что сопрограммы вроде "запоминают", куда они ушли, и переходят с этого момента (говоря простыми словами), так что вы может запустить много вещей, видимо, "параллельно". Но, тем не менее, все это выполняется в одном и том же потоке, поэтому на самом деле кажется, что оно выполняется только параллельно, потому что все выполняется между двумя кадрами.

Если у вас действительно есть трудоемкая задача, которую вы хотите выполнить в другом потоке, чем загляните в async await , которая является реальной многопоточностью Unity начиная с Unity 2017.

Однако Unity - , а не , сохранение потока означает, что большая часть API может использоваться только в основном потоке ...

0 голосов
/ 28 апреля 2018

Это потому, что вы застряли в сопрограмме. Вам нужно переместить доходность внутри цикла:

IEnumerator MyCoroutine ()
{
    Transform[] allChildren = GetComponentsInChildren<Transform>();
    foreach (Transform child in allChildren)
    {
        if (child.gameObject.GetComponent<MeshFilter>())
        {
            if (!child.gameObject.GetComponent<MeshCollider>())
            {
                child.gameObject.AddComponent<MeshCollider>();
            }
        }
        child.gameObject.tag = "CenterObject";
        yield return null;
    }
}

Даже если это большое количество детей, с которыми вы работаете в цикле, это может быть просто проблемой производительности.

...