Войти
ПрограммированиеФорумФизика

[Unity] С какой стороны объект попал в триггер при нефиксированной deltaTime

Страницы: 1 2 Следующая »
#0
12:09, 20 фев. 2018

Привет.

Столкнулся с такой проблемой. Не могу определить, с какой стороны заход в триггер происходит: сверху вниз или [любой другой вариант]. Фактически можно считать, что эта задача из Марио, когда нужно четко определить, прыгнул ли Марио сверху на врага, тогда враг убит, иначе Марио сам получает урон. Проблема в том, что иногда вызов триггера происходит слишком поздно (скачек фпс или хрен знает что ещё), и несмотря на то, что визуально игрок точно прыгнул сверху, внутри OnTriggerEnter2D это не определяется.

Определяю сверху или нет пока довольно топорно: в OnTriggerEnter2D смотрю, что бы velocity.y была меньше нуля у игрока (значит падаем вниз), и если это так, то сравниваем центры бокс коллайдеров: если центр бокс-коллайдера игрока выше центра бокс-коллайдера враг, то можем считать, что игрок прыгнул сверху. И вот иногда OnTriggerEnter2D вызывается слишком "поздно", когда игрок уже пролетел своим центром центр врага.

На игроке висит Rigidbody2D кинематик сугубо для вызовов тригггер-сообщений. Коллизии свои через рейкасты.

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

Я думаю, что всё из-за асинхронных вызовов Update и physics cycles (где и определяются пересечения коллайдеров), которые иногда происходят сильно "поздно" в сравнении с Update, если был скачек fps и персонаж за кадр преодалел слишком большое расстояние.

Подскажите, пожалуйста, как разрулить? Поможет ли перенос всей логики движения персонажа в FixedUpdate? Ну или в обычном Update в цикле сделать привязку к фиксированной дельта и при этом руками проверять все пересечения?
Есть ли более грамотный вариант?


#1
15:57, 20 фев. 2018

Все расчеты по физике всегда расчитываются в FixedUpdate - это функция вызывающаяся всегда раз в определенный fixed timestep (0.02 сек), в то время как Update вызывается каждый кадр и подходит только для визуализации (при этом в Update расчеты помножаешь на delta time, чтобы изображение не скакало). К тому же для экшен игры, я бы еще посоветовал уменьшить fixed timestep в двое (до 0.01 сек). Меняется в настройках Edit > Project Settings > Time (после изменения все встроенные в движок физические расчеты тоже будут высчитываться в двое (т.е. прыжки ниже, трение выше и тд)) И все что в FixedUpdate тоже будут в двое чаще вызываться, как плюс - зато можно делать игру на "более высоких скоростях", больше динамики и тд. - коллизии будут рассчитываться точнее, ситуаций когда коллайдер пролетел сквозь коллайдер будет гораздо меньше.

#2
16:03, 20 фев. 2018

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

#3
16:18, 20 фев. 2018

Tokarn
> А положение столкновения можно получить точно только при OnCollisionEnter
> (используя коллизию, то бишь коллайдер, а не триггер), оно будет включено в
> данные collision

Тут проблема, что при использованнии коллайдера вместо триггера объект никогда не зайдёт внутрь коллайдера, а нужно, чтобы заходил, только при этом так же нужно знать, с какой стороны. Триггер с эффектором рассмотрю.

Tokarn
> Все расчеты по физике всегда расчитываются в FixedUpdate
на deltaTime, коенчно же, умножаются все перемещения. Я полагал, что внутри FixedUpdate необходимо рассчитывать только если меняешь положение объекта через Rigidbody2D, а не через Transform.

Попробую всё перенести в FixedDelta.

Спасибо!

#4
16:27, 20 фев. 2018

Перенес в FixedUpdate, все умножения на Time.deltaTime заменил умножениями на Time.fixedDeltaTime.

Проблема осталась, иногда OnTriggerEnter2D вызывается слишком поздно, когда объект глубоко внутри коллайдера. Пробую разные варианты.

#5
16:37, 20 фев. 2018

Если в FixedUpdate умножение на deltatime в любом виде не требуется. В Update ты умножаешь, чтобы сгладить скачки FPS, в FixedUpdate никаких скачков нету, всегда через одно и то же время функция запускается

#6
16:40, 20 фев. 2018

Tokarn
Да, но я параметры всех величин, скорости, высоты прыжков и т.д. подобрал с учетом умножения на deltaTime, при переносе в FixedUpdate для быстрого теста все умножения нужно теперь же заменить на фиксированную дельту. А иначе они будут слишком большими, персонж за пределы экран будет вылетать при прыжке, например. Понятное дело, что если оставить FixedUpdate, то параметры один раз скорректировать и всё. Но суть не в этом.
Один фиг, не работает, иногда косяк так и остаётся. смотрю где я что не учёл

#7
16:43, 20 фев. 2018

deltatime это время между двумя кадрами предыдущим и текущим, оно рассчитывается по данным того же надежного счетчика, что и запускает FixedUpdate.
То бишь в Update умножая на deltatime ты сглаживаешь перемещение, и несмотря на то что между разными кадрами разное время, движение происходит ровно на столько, на сколько должно, не зависимо от кадров (но выполняется Update иногда реже, чем FixedUpdate, из-за чего может получится слепое пятно в просчетах). Советую перемещения делать не через Transform, а Rigidbody - оно интерполирует перемещение коллайдера и таких ситуаций как у тебя становится в разы меньше

#8
16:50, 20 фев. 2018

Tokarn
Про дельту тайм я в курсе, писал свой 2д движок когда-то давно-давно)

Окей, попробую через Rigidbody, спасибо.

#9
16:54, 20 фев. 2018

Я так понимаю, чтобы "Rigidbody - оно интерполирует перемещение коллайдера и таких ситуаций как у тебя становится в разы меньше "
Нужно выбрать интерполяцию в настройках Rigidbod2d?
11 | [Unity] С какой стороны объект попал в триггер при нефиксированной deltaTime

#10
17:03, 20 фев. 2018

Zackary
Лучше Collision Detection поменяй не на Discrete - это годится только для чего то навроде подбираемых объектов

#11
17:36, 20 фев. 2018

Вроде бы эта проблема ушла, сейчас сколько не тестил - всё срабатывает вовремя.

Но появилась другая: персонаж стал перемещаться довольно дёргано, пропала плавность. При уменьшении fixed timestep становится чуть лучше, но не хотелось бы её - игрушка для мобилок.
Блин, то одно, то другое.

#12
18:03, 20 фев. 2018

Если двигать через transform.Translate, и при этом в FixedUpdate, то всё плавно и коллизии срабатывают как надо.
Если двигать через body2d, то периодически какая-то дёрганность по время передвижения.

#13
19:19, 20 фев. 2018

В общем и это разрулил.

Фишка в том, что если двигать так: body.position += deltaMovement; то будут дёрганья.
А если так: body.MovePosition(body.position + deltaMovement); то всё в порядке. Хотя по идее ожидается одинаковое поведение обоих конструкций)

#14
21:47, 20 фев. 2018

Так синхронизируй deltaTime-physics  с deltaTime-render!
Zackary
> Фишка в том, что если двигать так: body.position += deltaMovement; то будут
> дёрганья.
> А если так: body.MovePosition(body.position + deltaMovement);
Может функция body.MovePosition делает что то вроде этого body.position += deltaMovement * dt ;

Страницы: 1 2 Следующая »
ПрограммированиеФорумФизика

Тема в архиве.