Когда я должен использовать скорость против addForce при работе с объектами игрока?

18

Я запутался в этих двух методах в рамках Unity. И то, и другое заставляет объект игрока двигаться, останавливаться, менять направление и т. Д. Когда один из них должен быть использован поверх другого, а когда уместен?

Роберт
источник
Связано
MichaelHouse
@ Byte56 оба вопроса задают о разных вещах
Роберт
1
Разные, но связанные. Вот почему они просто связаны, а не дубликаты. Показать это отображается в связанном столбце справа.
MichaelHouse

Ответы:

13

Вы будете использовать velocityдля перемещения объекта с постоянной скоростью (например, пули) и AddForce()добавить движение (например, движитель космического корабля). Также обратите внимание, что есть два «типа» движения; сила и импульс. Для космического корабля вы бы использовали импульс.

trojanfoe
источник
4
Можете ли вы описать, почему вы предпочитаете импульсы для двигателя космического корабля? На самом деле это может быть неидеальная подгонка, если вы применяете постепенное ускорение во времени, а не мгновенные изменения импульса из-за таких вещей, как удары оружия. Применительно к временному окну вы, как правило, будете нуждаться в силе (или ускорении, если не хотите, чтобы масса была фактором), в то время как мгновенно вы будете использовать импульс (или, соответственно,
speedChange
@DMGregory Да, это зависит от того, какую силу вы хотите добавить. В моем примере двигателя космического корабля, который представляет собой мгновенный прилив энергии, импульс является правильным выбором.
trojanfoe
2
Сразу было неясно, имели ли вы в виду кратковременную стрельбу с ориентационной струи или непрерывный ожог главного двигателя (иногда «подруливающее устройство» используется в научной фантастике немного обобщенно), поэтому я подумал, что мне следует уточнить, чтобы кто-то не попробовал используя импульсы для ракетного ускорителя. ;)
DMGregory
@DMGregory Действительно; моя космическая техническая терминология в значительной степени основана на фильмах :)
trojanfoe
@trojanfoe Иди играть в KSP. Мол, прямо сейчас.
user253751
21

Хотя уже есть принятый ответ, я думаю, что есть некоторые дополнительные детали, на которые стоит обратить внимание.

Используя скорость

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

  • Если несколько источников / сценариев пытаются изменить одну и ту же скорость Rigidbody, установив ее напрямую (т.е. body.velocity = foo ), то, какой бы из них ни был запущен последним, выигрыши, а другие имеют нулевой эффект. Это может привести к порядку ошибок обновления, в частности, заставляя объекты зависать или падать медленно (потому что ускорение вниз из-за гравитации переопределяется, прежде чем оно может накапливаться)

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

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

AddForce и Друзья

AddForce и аналогичные вспомогательные функции созданы для взаимодействия со всем, что происходит в мире физики. Если несколько источников / сценариев AddForce для Rigidbody, все эти эффекты добавляются вместе, чтобы создать чистое изменение в движении объекта (которое, в зависимости от того, как он рассчитывается, также может быть независимым от порядка). Это помогает избежать одного сценария, полностью подавляющего некоторый другой физический эффект.

AddForce поставляется в четырех вариантах с указанием необязательного параметра ForceMode , который полезен для разных целей:

ForceMode       |   Use
-----------------------------------------------------------------------
Force (default) |   Accelerate an object over 1 time step, based on its mass.
                |   Units: Newtons = kg * m/s^2
                |
Acceleration    |   Accelerate an object over 1 time step, ignoring its mass. (like gravity)
                |   Units: m/s^2
                |
Impulse         |   Instantaneously propel an object, based on its mass
                |   Units: N * s = kg * m/s
                |
VelocityChange  |   Instantaneously propel an object, ignoring its mass
                |   (like body.velocity = foo, except multiple scripts can stack)
                |   Units:  m/s

Если вы пытаетесь смоделировать непрерывный толчок с течением времени (например, что-то, что вы применяете при каждом FixedUpdate), например, за рулем автомобиля, или за горением ракеты, или за гравитационным колодцем, вам нужна сила или ускорение. (В зависимости от того, хотите ли вы, чтобы тяжелые предметы ускорялись медленнее)

Если вы моделируете внезапное, резкое изменение движения, например, стрельбу пули, отскакивание от взрыва или отскакивание от барьера, то вам скорее всего понадобится Impulse или VelocityChange.

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

public static void AccelerateTo(this Rigidbody body, Vector3 targetVelocity, float maxAccel)
{
    Vector3 deltaV = targetVelocity - body.velocity;
    Vector3 accel = deltaV/Time.deltaTime;

    if(accel.sqrMagnitude > maxAccel * maxAccel)
        accel = accel.normalized * maxAccel;

    body.AddForce(accel, ForceMode.Acceleration);
}

Причина, по которой я называю все эти «вспомогательные функции», заключается в том, что технически вы могли бы достичь всех одинаковых целей:

 body.velocity += suitablyCalculatedDeltaV;

( Я думаю . Возможно, физика Unity на базе PhysX / Box2D решает изменения буфера отдельно через AddForce, но я не видел очевидных последствий этого)

Итак, в конце концов, что эти функции действительно дают нам, так это ясность намерений . Когда я хочу применить постепенную силу, мне не нужно помнить, чтобы умножить мой deltaV на Time.deltaTime и разделить на массу, я просто говорю, что хочу ForceMode.Force, и он обрабатывается правильным и последовательным образом. И когда я или кто-то другой позже итерируем свой код, сразу становится ясно, что я имел в виду, без необходимости декодировать вычисления времени и массы, чтобы понять это.

Д.М.Григорий
источник
6

В дополнение к ответу троянца , Angry Birds vs Car Racing. Два основных и разных примера этих методов ( AddForceи velocityсоответственно). Например, в Angry Birds использование скорости немного сложнее, так как вам бы пришлось самому устанавливать траекторию снаряда, например,

Когда я использую AddForce в Angry Birds, я бы использовал,

_birdRigidbody.AddForce(new Vector2(5,5));

В то время как когда я использую скорость, то я бы обрабатывал траекторию, используя

x = v*t*Cos(theta) y = v*t*Sin(theta) - 0.5 * g * t *t

Или как то так.

В то время как в игре Car Racing вам придется постоянно контролировать скорость, а не как Angry Birds, то есть Shoot и все такое. Так что в этом сценарии дескриптор velocityболее полезен, чем AddForce.

Надеюсь, вы понимаете. По крайней мере, немного.

Хамза Хасан
источник
1
Ваш пример AngryBirds, вероятно, должен использовать мгновенное изменение импульса (например, Impulse или VelocityChange) при отпускании рогатки, а не ForceMode.Force по умолчанию, который имитирует его действие во временном окне. Вы можете настроить числа так, чтобы получить эквивалентное поведение при любом подходе, но если вы измените свой фиксированный временной шаг, у силового решения будет другой выход (так как оно интегрирует силу в течение более длинного или более короткого временного интервала), в то время как импульс остается последовательным, как желательно, потому что он представляет собой только момент выпуска.
DMGregory
0

Rigidbody Velocity и Rigidbody Addforce - две запутанные функции в Unity 3D, и часто начинающие не понимают их различий. В этой статье мы собираемся обсудить разницу между RigidBody.velocity и RigidBody.addforce.

В обоих случаях, будь то Addforce или функция скорости, мы будем использовать термин «сила», чтобы объяснить их.

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

Например

body.velocity = new Vector3 (0,0,5);

Допустим, вы добавили 5f в позиции z, и эта сила будет добавлена, когда вы нажмете клавишу W. Поэтому, когда вы нажмете клавишу «W», объект мгновенно запустится со скоростью 5. Это похоже на то же самое, если вы добавляете силу, используя эту функцию на автомобиле, эта машина будет запускаться со скоростью 5.

body.velocity = new Vector3 (0,0,200);

И если вы допустите изменение значения на 200, а затем после сохранения нажмите W. Автомобиль начнет движение со скоростью 200 с момента запуска, что невозможно в реальном мире.

Теперь, если вы говорите о Rigidbody.addforce

Продолжая наш автомобильный пример. если вы добавите силу 200 к машине

body.addforce (0,0,200);

Автомобиль не начнет двигаться со скоростью 200, если мы нажмем W, но он начнет медленно, а затем увеличит свою скорость и остановится в соответствии со значением Drag.

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

Вы можете использовать Rigidbody.velocity, где вы просто хотите переместить свой объект, чтобы реагировать мгновенно, как прыжок игрока, и результат этой силы исчезнет сразу после прыжка, и вы можете использовать Rigidbody.addforce, где вам нужен медленный старт, а затем непрерывное движение, как ракета. Если вы используете Rigidbody.addforce в прыжке, Player / Object некоторое время будет оставаться в космосе, а затем вернется на землю.

(источник)

Нуман Хамза
источник
Вы должны хотя бы попытаться адаптировать свой пост к формату ответа Stack Exchange :)
Vaillancourt