В Unity, когда мне следует использовать сопрограммы вместо вычитания Time.deltaTime в Update ()? - PullRequest
5 голосов
/ 27 апреля 2020

Ниже приведен простой пример различия, которое я хотел бы выделить.

Использование сопрограмм:

public float repeatRate = 5f;
void Start()
{
    StartCoroutine("RepeatSomething");
}
IEnumerator RepeatSomething()
{
    while (true)
    {
        yield return new WaitForSeconds(repeatRate);
        // Do something
    }
}

Использование Update() и Time.deltaTime:

public float repeatRate = 5f;
private float timer = 0;
void Update()
{
    if (timer < 0)
    {
        // Do something
        timer = repeatRate;
    }
    timer -= Time.deltaTime;
}

Когда я должен использовать одно в отличие от другого и каковы преимущества / недостатки каждого?

Ответы [ 5 ]

2 голосов
/ 28 апреля 2020

В большинстве случаев ответом будет.

В общем, разница в производительности между обновлением и сопрограммой не имеет значения. Просто следуйте подходу, который подходит вам лучше всего, но используйте гораздо более производительный MEC Coroutines вместо Unity Coroutine, если вы хотите следовать подходу, подобному Coroutine.

ПРОСТОЕ ИСПОЛЬЗОВАНИЕ

Как упоминалось на форуме Unity в целом "Coroutines полезны для выполнения методов на нескольких кадрах [и затем забудьте об этом]."

Если вы планируете использовать только несколько из них (менее 10k?) , тогда у вас все в порядке и с Unity Coroutines.

ADVANCED USAGE

В настоящий момент Unity поддерживает Task / Asyn c, но производительность все еще довольно низкий. Так что вы можете подумать об использовании Coroutines для имитации функциональности Async.

В этом случае вы можете даже использовать Coroutines для удаления всех (или большей части) ваших Update циклов, например, в пример, который вы опубликовали.

Это полезно с точки зрения производительности, особенно в вашем конкретном случае c, потому что когда вы используете Update l oop, вы постоянно проверяете if (timer < 0), даже когда ты ничего не делаешь. И даже пустое обновление L oop все еще является проблемой производительности.

С другой стороны, вы можете просто запускать и останавливать Coroutines, когда происходит событие. И когда Coroutine останавливается, стоимость производительности становится равной 0.

Если вы хотите следовать этому методу, я настоятельно рекомендую использовать ME C сопрограммы , которая устраняет все проблемы с производительностью, вызванные сопрограммами Unity. (и имеют одинаковую функциональность).


В ЗАКЛЮЧЕНИИ

  1. В большинстве случаев эта разница в производительности не имеет значения
  2. MEC Coroutines немного более производительный, чем обновление l oop
  3. Update l oop обычно более производительный, чем Unity Coroutines
  4. Unity Coroutines следует использовать только для простых синхронизированных задач, которые случаются редко

PS: этот ответ о единой сопрограмме может помочь вам понять, как они работают в глубине.
PPS: этот старый ответ может дать вам дальнейшее понимание, но оно немного устарело, особенно когда речь идет о сборке мусора.

1 голос
/ 27 апреля 2020

Никогда не используйте сопрограммы.

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

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

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

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

В конечном итоге вы даже пойдете на компромисс по качеству кофе, потому что его ароматы больше не кажутся такими важными. Вы пристрастились к молочным продуктам, сахару и кофе, а не только к кофеину.

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

То, что казалось решение стало проблемой. Затем начинают появляться действительно серьезные проблемы с вашим здоровьем и психическим состоянием.

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

Всегда.

1 голос
/ 27 апреля 2020

Честно говоря, они будут выполнять одну и ту же задачу. Они оба будут выполнять каждый отдельный кадр (и в вашем случае проверьте, прошло ли 5 ​​секунд с момента их первоначального выполнения). Однако есть несколько ключевых отличий . А именно, наиболее важным является порядок исполнения. Coroutines будет всегда работать после Update(). Если по какой-то причине в Update() происходит что-то, что необходимо обновить для обновления Coroutine правильной информацией, это важно. Но обычно это не так.

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

1 голос
/ 27 апреля 2020

С каждым выходом вы фактически создаете новый объект, как говорите new WaitForSeconds(). Однако разница все же не так существенна. С другой стороны, сопрограммы более удобочитаемы, особенно если учесть, что вам нужно использовать более одного выхода в одной сопрограмме с разным временем ожидания, реализация такой вещи в Update сделает ваш код довольно грязным.

1 голос
/ 27 апреля 2020

Простой ответ: используйте в зависимости от того, что читается лучше (насколько я знаю, заметной разницы в производительности нет). Я бы (обычно) использовал Coroutines, потому что это поможет вам упорядочить ваше Обновление l oop, и я чувствую, что их, как правило, немного проще настроить (вам не нужно создавать переменную для вашего таймера и т. Д.) 1005 *.)

...