Void fixedupdate что это

Void fixedupdate что это

Во многих туториалах говорят, что Фикс используется для физики, при этом встречал даже в официальных туториалах, что используют обычный Апдейт. Так в каких конкретно случаях надо использовать Фикс? Чем черевато, если вместо него использовать Апдейт? Можно ли использовать обе функции в одном скрипте?

Re: Update и FixedUpdate

Re: Update и FixedUpdate

Re: Update и FixedUpdate

Re: Update и FixedUpdate

Откуда такая информация?

Re: Update и FixedUpdate

Откуда такая информация?

Re: Update и FixedUpdate

Re: Update и FixedUpdate

Re: Update и FixedUpdate

Re: Update и FixedUpdate

Лучше не делать, но всё-таки будет работать? Просто не понятен эффект, чем это чревато?

Re: Update и FixedUpdate

Re: Update и FixedUpdate

Я так понял, что если очень низкий фпс и игра считай что в режиме недопаузы, FixedUpdate будет стабильно тикать по часам компьютера. И т.к. физика в юнити в каком-то смысле отделена от общей среды, то если посылать сигналы с Update(), они будут как управление марсоходом, который в данный момент катится с горы где-то на Марсе. Т.е. все ваши действия будут неадекватны по отношению к физике.

И наоборот, если вы логику кинете в FixedUpdate, это при ведёт к линейности вызовов при разной нагрузке на определённые фреймы, что вызовет скачкообразные микролаги.

Re: Update и FixedUpdate

Во многих туториалах говорят, что Фикс используется для физики, при этом встречал даже в официальных туториалах, что используют обычный Апдейт. Так в каких конкретно случаях надо использовать Фикс? Чем черевато, если вместо него использовать Апдейт? Можно ли использовать обе функции в одном скрипте?

У меня на fixedDeltaTime акселерометр никак не реагировал. Ставишь TimeScale = 0.5 например, или на 0, вся сцена неподвижна, а объект привязанный к акселерометру работает в полную силу.
А на обычном deltatime все ОК.
Так что смотрите внимательней с этим.

Источник

Как мы оптимизировали скрипты в Unity

Существует множество отличных статей и туториалов о производительности в Unity. Этой статьёй мы не пытаемся заменить или улучшить их, это всего лишь краткое изложение шагов, сделанных нами после прочтения этих статей, а также шагов, позволивших решить наши проблемы. Настоятельно рекомендую вам как минимум изучить материалы на https://learn.unity.com/.

В процессе разработки своей игры мы столкнулись с проблемами, время от времени вызывавшими торможения игрового процесса. Потратив какое-то время в Unity Profiler, мы обнаружили два типа проблем:

Поиск слабых мест

Цель этой статьи — не написать туториал по использованию профилировщика; я хотел просто рассказать о том, что нас в основном интересовало в процессе профилирования.

Unity Profiler — всегда самый лучший способ поиска причин задержек в скриптах. Настоятельно рекомендую профилировать игру непосредственно в устройстве, а не в редакторе. Поскольку наша игра создавалась для iOS, мне нужно было подключить устройство и использовать показанные на изображении Build Settings, после чего профилировщик подключался автоматически.

Void fixedupdate что это. Смотреть фото Void fixedupdate что это. Смотреть картинку Void fixedupdate что это. Картинка про Void fixedupdate что это. Фото Void fixedupdate что это

Build Settings (параметры сборки) для профилирования

Если вы попробуете загуглить «Random lag in Unity» или другой похожий запрос, то обнаружите, что большинство людей рекомендует сосредоточиться на сборке мусора, поэтому именно так я и поступил. Мусор генерируется каждый раз, когда вы прекращаете использовать какой-то объект (экземпляр класса), после чего время от времени запускается сборщик мусора Unity для уборки беспорядка и освобождения памяти, что требует безумного количества времени и приводит к падению частоты кадров.

Как найти в профилировщике скрипты, вызывающие появление мусора?

Void fixedupdate что это. Смотреть фото Void fixedupdate что это. Смотреть картинку Void fixedupdate что это. Картинка про Void fixedupdate что это. Фото Void fixedupdate что это

Параметры Profiler для сборки мусора

Ваша задача — добиться одних нулей в столбце GC alloc для геймплейной сцены.

Ещё один хороший способ — отсортировать записи по «Time ms» (времени исполнения) и оптимизировать скрипты, чтобы они занимали как можно меньше времени. Этот шаг имел для нас огромное влияние, потому что один из наших компонентов содержал большой цикл for, для выполнения которого требовалась целая вечность (да, мы пока не нашли способа избавиться от цикла), поэтому оптимизация времени выполнения всех скриптов была для нас абсолютно необходима, ведь нам требовалось сэкономить время выполнения на этом затратном цикле for, сохраняя при этом стабильную частоту в 60 fps.

На основании данных профилирования я разделил оптимизацию на две части:

Часть 1: боремся с мусором

В этой части я расскажу, что мы делали, чтобы избавиться от мусора. Это самые фундаментальные знания, которые должен понимать любой разработчик; они стали важной частью нашего ежедневного анализа в каждом pull/merge request.

Первое правило: никаких новых объектов в методах Update

В идеале методы Update, FixedUpdate и LateUpdate не должны содержать ключевых слов «new». Всегда нужно использовать то, что у вас уже есть.

Иногда создание нового объекта сокрыто в некоторых внутренних методах Unity, поэтому оно не так очевидно. Мы расскажем об этом позже.

Второе правило: создавать один раз и использовать многократно!

По сути, это означает, что выделять память для всего, что можно, следует в методах Start и Awake. Это правило очень похоже на первое. На самом деле это просто ещё один способ устранения ключевых слов «new» из методов Update.

Вот примеры внесённых нами изменений:

Выделение памяти под списки в методе Start, их очистка (Clear) и повторное использование при необходимости.

Хранение ссылок и повторное использование их следующим образом:

То же относится к методу FindGameObjectsWithTag или любому другому методу, возвращающему новый массив.

Третье правило: остерегайтесь строк и избегайте их конкатенации

Когда дело доходит до создания мусора, то строки ужасны. Даже простейшие операции со строками могут создавать много мусора. Почему? Строки — это просто массивы, и эти массивы неизменяемы (immutable). Это означает, что каждый раз, когда вы конкатенируете две строки, создаётся новый массив, а старый превращается в мусор. К счастью, можно использовать StringBuilder, чтобы избежать или минимизировать такое создание мусора.

Вот пример того, как можно улучшить ситуацию:

С показанным выше примером всё в порядке, но в нём есть ещё много возможностей для улучшения кода. Как видите, почти всю строку можно считать статической. Мы разделяем строку на две части для двух объектов UI.Text. Сначала одна содержит только статический текст «Player » + name + » has score «, который можно назначить в методе Start, а вторая содержит значение счёта, которое обновляется в каждом кадре. Всегда делайте статические строки действительно статическими и генерируйте их в методе Start или Awake. После этого усовершенствования почти всё в порядке, но по-прежнему генерируется немного мусора при вызове Int.ToString(), Float.ToString() и т.п.

Мы решили эту проблему генерацией и предварительным выделением памяти под все возможные строки. Это может показаться глупой тратой памяти, но такое решение идеально соответствует нашим потребностям и полностью решает проблему. Итак, в конечном итоге мы получили статический массив, доступ к которому можно напрямую получать доступ при помощи индексов, чтобы брать нужную строку, обозначающую число:

Четвёртое правило: кешировать значения, возвращаемые методами доступа

Это может быть очень сложно, потому что даже простой метод доступа (accessor), наподобие показанного ниже, генерирует мусор:

Старайтесь избегать использования методов доступа в методе Update. Вызывайте метод доступа только один раз в методе Start и кешируйте возвращаемое значение.

В общем случае я рекомендую НЕ вызывать никаких методов доступа к строкам или методов доступа к массивам в методе Update. В большинстве случаев достаточно один раз получить ссылку в методе Start.

Вот ещё два распространённых примера ещё одного неоптимизированного кода методов доступа:

Пятое правило: используйте функции, не выполняющие выделение памяти

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

Для этого конкретного случая можно найти не выделяющую память функцию под названием

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

Шестое правило: не используйте LINQ

Просто не делайте этого. Я имею в виду, что не нужно использовать его в любом коде, который выполняется часто. Знаю, при использовании LINQ код проще читается, но во многих случаях производительность и выделение памяти такого кода ужасны. Разумеется, его можно иногда использовать, но, если честно, в своей игре мы вообще не применяем LINQ.

Седьмое правило: создавать один раз и использовать многократно, часть 2

На этот раз речь идёт о пулинге объектов. Я не буду вдаваться в подробности пулинга, потому что об этом говорилось много раз, например, изучите этот туториал: https://learn.unity.com/tutorial/object-pooling

В нашем случае используется следующий сценарий пулинга объектов. У нас есть сгенерированный уровень, заполненный препятствиями, существующими в течение определённого периода времени, пока игрок не пройдёт эту часть уровня. Экземпляры таких препятствий создаются из префабов в случае соблюдения определённых условий. Код находится в методе Update. Этот код совершенно неэффективен с точки зрения памяти и времени выполнения. Мы решили проблему, сгенерировав пул из 40 препятствий: при необходимости мы получаем препятствия из пула и возвращаем объект обратно в пул, когда он больше не нужен.

Восьмое правило: внимательнее с упаковкой-преобразованием (Boxing)!

Boxing генерирует мусор! Но что такое boxing? Чаще всего boxing возникает, когда вы передаёте тип значения (int, float, bool и т.д.) в функцию, которая ожидает параметр типа Object.

Вот пример boxing-а который нам нужно исправить в нашем проекте:

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

Также у нас есть сеттер, задающий значения в этом словаре:

Boxing здесь довольно очевиден. Можно вызвать функцию следующим образом:

Тогда значение «12» подвергается boxing-у и это генерирует мусор.

Мы решили проблему, создав отдельные контейнеры данных для каждого примитивного типа, а предыдущий контейнер Object используется только для типов-ссылок.

Также у нас есть отдельные сеттеры для каждого типа данных:

И все эти сеттеры реализованы таким образом, что вызывают одинаковую обобщённую функцию:

Проблема boxing-а решена!

Девятое правило: циклы всегда под подозрением

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

В общем случае мы стремимся избавиться от циклов в методах Update, но если без них не обойтись, то мы по крайней мере избегаем любого выделения памяти в таких циклах. Итак, следуйте правилам 1–8 и примените их к циклам в целом, а не только в методах Update.

Десятое правило: никакого мусора во внешних библиотеках

В случае, если выяснится, что часть мусора генерируется кодом, скачанным из Asset store, то у этой проблемы есть множество вариантов решения. Но прежде чем выполнять реверс-инжиниринг и отладку, просто снова зайдите в Asset store и обновите библитеку. В нашем случае все используемые ассеты по-прежнему поддерживались авторами, продолжающими выпускать улучшающие производительность обновления, поэтому это решило все наши проблемы. Зависимости должны быть актуальными! Я лучше избавлюсь от библиотеки, чем сохраню неподдерживаемую.

Часть 2: максимально снижаем время выполнения

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

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

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

Многие из этих правил пересекаются с представленными в первой части статьи. Обычно производительность создающего мусор кода ниже по сравнению с кодом без создания мусора.

Первое правило: правильный порядок выполнения

Переместите код из методов FixedUpdate, Update, LateUpdate в методы Start и Awake. Знаю, это звучит безумно, но поверьте, если вы углубитесь в свой код, то найдёте сотни строк кода, которые можно переместить в методы, исполняемые только один раз.

В нашем случае такой код обычно связан с

Второе правило: выполняйте код только тогда, когда это необходимо

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

Так как на каждом уровне есть всего несколько собираемых предметов, то не имеет никакого смысла изменять текст UI в каждом кадре. Поэтому мы изменяем текст только при изменении числа.

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

Как бы то ни было, этого всё равно было для нас недостаточно, и мы хотели реализовать совершенно обобщённое решение, поэтому создали библиотеку, реализующую Flux в Unity. Это привело к очень простому решению, при котором всё состояние игры хранится в объекте «Store», а все элементы UI и другие компоненты уведомляются при изменении состояния и реагируют на это изменение без кода в методе Update.

Третье правило: циклы всегда под подозрением

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

Четвёртое правило: For лучше, чем Foreach

Цикл Foreach очень легко написать, но «очень сложно» выполнять. Внутри цикла Foreach используются Enumerator для итеративной обработки набора данных и возврата значения. Это сложнее, чем итерация индексов в простом цикле For.

Поэтому в нашем проекте мы по возможности заменили циклы Foreach на For:

В нашем случае с большим циклом for это изменение очень значимо. Простой цикл for ускорил код в два раза.

Пятое правило: массивы лучше, чем списки

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

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

Шестое правило: операции с Float лучше, чем операции с векторами

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

Мы вносили подобные изменения:

Седьмое правило: искать объекты правильно

Всегда думайте, действительно ли нужно использовать метод GameObject.Find(). Этот метод тяжёл и занимает безумное количество времени. Никогда не следует использовать такой метод в методах Update. Мы выяснили, что большинство наших вызовов Find можно заменить прямыми ссылками в редакторе, что, разумеется, гораздо лучше.

В случае, если так сделать невозможно, то хотя бы рассмотрите возможность использования меток (Tag) и поиска объекта по его метке при помощи GameObject.FindWithTag.

Итак, в общем случае: Прямая ссылка > GameObject.FindWithTag() > GameObject.Find()

Восьмое правило: работайте только с относящимися к делу объектами

В нашем случае это было важно для распознавания коллизий при помощи RayCast-ов (CircleCast и т.п.). Вместо распознавания коллизий и принятия решения о том, какие из них важны, в коде, мы переместили игровые объекты на соответствующие слои, чтобы можно было вычислять коллизии только для нужных объектов.

Девятое правило: правильно используйте метки

Нет никаких сомнений, что метки очень полезны и могут улучшить производительность кода, но помните, что существует только один правильный способ сравнения меток объектов!

Десятое правило: опасайтесь хитростей с камерой!

Так легко использовать Camera.main, но производительность этого действия очень плоха. Причина заключается в том, что за кулисами каждого вызова Camera.main движок Unity на самом деле выполняет для получения результата FindGameObjectsWithTag(), поэтому мы уже понимаем, что часто его вызывать не нужно, и лучше всего решить эту проблему, кешировав ссылку в методе Start или Awake.

Одиннадцатое правило: LocalPosition лучше, чем Position

Везде, где это возможно, используйте для геттеров и сеттеров Transform.LocalPosition вместо Transform.Position. Внутри каждого вызова Transform.Position выполняется гораздо больше операций, например, вычисление глобальной позиции в случае вызова геттера или вычисление локальной позиции из глобальной в случае вызова сеттера. В нашем проекте выяснилось, что можно использовать LocalPositions в 99% случаев использования Transform.Position, и в коде при этом не нужно делать никаких других изменений.

Двенадцатое правило: не использовать LINQ

Об этом уже говорили в первой части. Просто не используйте его, вот и всё.

Тринадцатое правило: не бойтесь (иногда) нарушать правила

Иногда даже вызов простой функции может быть слишком затратным. В этом случае всегда следует рассмотреть возможность встраивания кода (Code Inlining). Что это значит? По сути, мы просто берём код из функции и копируем его непосредственно в место, где хотим использовать функцию, чтобы избежать вызовов дополнительных методов.

В большинстве случаев это не окажет никакого влияния, потому что встраивание кода выполняется автоматически на этапе компиляции, но существуют определённые правила, по которым компилятор решает, должен ли встраиваться код (например, виртуальные методы никогда не встраиваются; подробнее об этом см. в https://docs.unity3d.com/Manual/BestPracticeUnderstandingPerformanceInUnity8.html). Поэтому просто откройте профилировщик, запустите игру на целевом устройстве и посмотрите, можно ли что-то улучшить.

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

Источник

MonoBehaviour.FixedUpdate()

Success!

Thank you for helping us improve the quality of Unity Documentation. Although we cannot accept all submissions, we do read each suggested change from our users and will make updates where applicable.

Submission failed

For some reason your suggested change could not be submitted. Please try again in a few minutes. And thank you for taking the time to help us improve the quality of Unity Documentation.

Description

Frame-rate independent MonoBehaviour.FixedUpdate message for physics calculations.

MonoBehaviour.FixedUpdate has the frequency of the physics system; it is called every fixed frame-rate frame. Compute Physics system calculations after FixedUpdate. 0.02 seconds (50 calls per second) is the default time between calls. Use Time.fixedDeltaTime to access this value. Alter it by setting it to your preferred value within a script, or, navigate to Edit > Settings > Time > Fixed Timestep and set it there. The FixedUpdate frequency is more or less than Update. If the application runs at 25 frames per second (fps), Unity calls it approximately twice per frame, Alternatively, 100 fps causes approximately two rendering frames with one FixedUpdate. Control the required frame rate and Fixed Timestep rate from Time settings. Use Application.targetFrameRate to set the frame rate.

Use FixedUpdate when using Rigidbody. Set a force to a Rigidbody and it applies each fixed frame. FixedUpdate occurs at a measured time step that typically does not coincide with MonoBehaviour.Update.

In the following example, the number of Update calls is compared against the number of FixedUpdate calls. FixedUpdate executes 50 times per second. (The game code runs around 200 fps on a test machine.)

Is something described here not working as you expect it to? It might be a Known Issue. Please check with the Issue Tracker at issuetracker.unity3d.com.

Copyright ©2021 Unity Technologies. Publication Date: 2021-12-03.

Источник

Движение с коллизией через Update и FixedUpdate, что такое «телепортация» в контексте физического движка в Unity?

Что подразумевают, когда говорят «телепортация» в контексте передвижения физического объекта?

2 ответа 2

Как работает любой физический движок (в геймдеве)

Дискретизация

Void fixedupdate что это. Смотреть фото Void fixedupdate что это. Смотреть картинку Void fixedupdate что это. Картинка про Void fixedupdate что это. Фото Void fixedupdate что это

Как мы видим, версия с fps = 10 хоть и похожа на наш синус, но есть явные “промахи». Или, другими словами, чем меньше шаг дискретизации, тем более точный получается результат на выходе.

А что там все-таки с физикой?

Возьмем простейший пример:

Void fixedupdate что это. Смотреть фото Void fixedupdate что это. Смотреть картинку Void fixedupdate что это. Картинка про Void fixedupdate что это. Фото Void fixedupdate что это

Двигающийся объект и стена-коллайдер перед ним, пока что в настройках ничего не трогаем и пытаемся двигать наш объект кодом, который написан во всех туториалах по Unity:

Void fixedupdate что это. Смотреть фото Void fixedupdate что это. Смотреть картинку Void fixedupdate что это. Картинка про Void fixedupdate что это. Фото Void fixedupdate что это

А теперь попробуем все то же самое сделать через Update и Transform.Translate :

Void fixedupdate что это. Смотреть фото Void fixedupdate что это. Смотреть картинку Void fixedupdate что это. Картинка про Void fixedupdate что это. Фото Void fixedupdate что это

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

Void fixedupdate что это. Смотреть фото Void fixedupdate что это. Смотреть картинку Void fixedupdate что это. Картинка про Void fixedupdate что это. Фото Void fixedupdate что это

С передвижением через FixedUpdate объект не дергается и не отлетает в рандомные стороны.

Почему так происходит?

3 раза меньше, поэтому и кажется, что объекты внутри и куб дергается.

Что делать с большими скоростями?

Цель: задать большую скорость объекту. Получается что-то такое:

Void fixedupdate что это. Смотреть фото Void fixedupdate что это. Смотреть картинку Void fixedupdate что это. Картинка про Void fixedupdate что это. Фото Void fixedupdate что это

Для таких ситуаций существует целый набор разных CCD (Continuous Collision Detection) алгоритмов:

Void fixedupdate что это. Смотреть фото Void fixedupdate что это. Смотреть картинку Void fixedupdate что это. Картинка про Void fixedupdate что это. Фото Void fixedupdate что это

Они разные и нужны для разных ситуаций, какие-то быстрые, какие-то медленные, тема интересная, но вопрос не об этом, так остановимся на самом “простом” Continuous режиме. После переключения наш объект остановится из-за преграды, вот в принципе и все, это просто работает. Логика там простая: вместо проверки на каждом вызове FixedUpdate физический движок до перемещения объекта под влиянием каких-то сил проверяет специальными алгоритмами (в этом и заключается их различие), не сталкивается ли объект с чем-то во время движения в этом кадре.

Почему нельзя перемещать физические объекты в Update?

Потому что логический и физический движки – это два разных потока. Unity самостоятельно ими управляет, но это не значит, что их нельзя сломать.

Void fixedupdate что это. Смотреть фото Void fixedupdate что это. Смотреть картинку Void fixedupdate что это. Картинка про Void fixedupdate что это. Фото Void fixedupdate что это

С точки зрения физического движка неподвижный элемент сменил свою позицию – это и есть телепортация. А поскольку физический движок ничего не знает о движении объект – просчитывать коллизии с помощью CCD он не будет.

А как же алгоритмы CCD?

Может показаться, что перенос Transform кода в FixedUpdate может как-то решить проблему, но нет, это будет все та же телепортация, только с другой частотой.

Горькая, но все же пилюля

Так почему же это решение не самое оптимальное?

Чаще считается физика – больше нагрузка на ЦП. Обычно такое решение не самое оптимальное, но “обычно” =/= “всегда”, так что и такое применяют.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *