Что такое angular drag unity
Как работает Drag в физике Unity
Осознавая что мои статьи похожи на восторг человека, впервые увидевшего какую-то (многим уже давно знакомую) вещь, все же решил написать очередную. Причина — заинтересовавший меня параметр drag у компонента Rigidbody. Объяснений и, тем более, формул — как он работает — руководства не дают. Поэтому разбираться придется самому.
Если кому-то лень читать, можно перелистать вниз, где находится найденный алгоритм того, как в Unity работает замедление с использованием drag.
При знакомстве с физикой в Unity первое, чему учат, это тому, что Rigidbody — воплощение физических свойств объекта. У него есть пара параметров, задающих его взаимодействие с окружающим миром. Собственно, наиболее значимый для динамических объектов: масса. С ней все интуитивно понятно: закон Ньютона и все такое… Приложили силу кратковременно — получили импульс и, соответственно, изменили скорость объекта. Прикладываем длительное время: получаем ускорение в зависимости от массы.
Кроме этого, у Rigidbody есть интересный параметр — drag. Выражаясь словами разработчиков: параметр drag задает drag объекта. На их языке drag — это замедление, торможение. Других объяснений — не дается. Говоря о физике и торможении, в голову приходит что-то из баллистики (аэродинамики, гидродинамики и пр.). Возможно, drag — это некий коэффициент, пропорциональный квадрату скорости. Это было бы разумно. Но.
Простой опыт показывает, что в Unity тела с большим значением drag не двигаются вообще. Гравитация на них не влияет, толкнуть их невозможно. Но при этом они стоят, то есть квадрат их скорости равен нулю. Значит тут все не так просто… или же, наоборот, не все так сложно. Физика в компьютерных играх должна просчитываться быстро, а значит возможны упрощения относительно реальной физической модели. Хотя реализовать игру, скажем, с релятивистскими эффектами было бы забавно…
Первый вопрос, которым я задался: хотя бы, масса в Unity ведет себя как масса? Эксперимент показал, что — да.
Для начала, в простой сцене я запустил шарик с массой 1 с высоты 5 метров на плоскость. Триггер на плоскости останавливал таймер, так что я мог наблюдать время падения шарика.
Расчетное время падения для него должно составлять: t = sqrt(2*h/g), где h — высота, g — ускорение свободного падения. В нашем случае (h=5м, g=9.81м/с^2) t ≈ 1.0096.
Запуск показал значение 1.02, что близко к нужному.
Встроенная гравитация — это хорошо. Хотелось бы проверить, не жульничает-ли она? Отключаем гравитацию для Rigidbody и взамен вручную создаем действующую силу:
Результат оказался тот же самый (t=1.02). Неплохо.
Для действующей силы были затем использованы несколько разных значения. И всегда изменение действующей силы (rb.AddForce(0, xxx, 0);) вызывало изменение времени «падения», совпадающее с расчетным. Так что модель взаимодействия сил и массы оказалась вполне знакомой, ньютоновской.
Далее для проверки и сравнения встроенного физического движка и имитируемого, я создал два шарика. Один двигался под действием гравитации, другой под действием скрипта. Причем в этот раз никаких сил не было. Изменения в скорости считались «вручную» в коде.
Для начала стоило проверить простое падение без замедления (drag=0). Код, двигающий второй шарик был довольно прост:
rb — это компонент Rigidbody сферы. gForceVector — вектор гравитации (0, 9.81, 0).
Пока все совпадает.
Теперь, левому шарику увеличиваем drag (drag=2). Он стал падать медленнее:
Интересный факт. Увеличение параметра drag до больших значений (бо́льших или равных примерно 50) приводило к тому, что шарик вообще не двигался. Изменение массы объекта никак не влияло на этот факт, что привело к мысли, что параметр drag — кинематический, то есть он зависит (и влияет) на положение, скорость, ускорение и т.д., не принимая в расчет силы или импульс.
Что еще могло влиять на алгоритм, где фигурировал drag? Возможно, частота обновления физики. Хотя это означало бы не самый лучший ход со стороны разработчиков. Но чем черт не шутит. Поменяем время обновления физики до 0.005 секунд.
Зависимость все же имеется. Однако, похоже, это вычислительные ошибки. Дальнейшие увеличения частоты обновления физики существенно время падения не меняют. Что, кстати, означает, что где-то в коде разработчиков должно быть что-то вроде «. *Time.fixedDeltaTime«.
Итак, что мы знаем про параметр drag? Он — кинематический (считается после действия всех сил). Умножается (хотя возможно и не он сам) на Time.fixedDeltaTime и уменьшает скорость. Самое простое, что можно было бы придумать с такими условиями, выглядит примерно так:
Новое действие выглядит довольно примитивно: одно умножение и одно вычитание (с поправкой на то, что действия осуществляются с векторами). Однако, с чего-то нужно начать. Проверяем этот код, для удобства автоматически присваивая переменной myDrag (из скрипта второй сферы) значение параметра drag первой сферы.
drag=1
drag=3
drag=15
drag=50
Собственно, здесь оба шарика так и не начали движение. Мне просто надоело ждать.
Итак, результат получился для меня неожиданный. Примитивный алгоритм, который задумывался как начальная точка, от которой бы я дальше отталкивался — оказался конечной точкой. Похоже, именно так и считается замедление в Unity с использованием параметра drag. С другой стороны — проще, значит быстрее (в плане времени выполнения).
Дальнейшие эксперименты расхождений между моим скриптом и встроенной физикой почти не показали. Почти. Оставалась одна мелочь. При значении drag=100 мой второй, движимый скриптом шарик, величественно поплыл вверх.
drag=100
В общем-то, этого следовало ожидать, исходя из алгоритма. Однако, в Unity подобного не наблюдается. Следовательно, нам осталась одна простейшая модификация кода:
Теперь, «отрицательное» движение исключено и мы имеем полноценную имитацию действия сил и торможения движка Unity.
Физический аналог непосредственно параметра drag подобрать проблематично. Можно лишь сказать, что он определяет нелинейное трение (или нелинейное сопротивление — кому как удобнее). При этом сам алгоритм прост и, вероятно, быстро выполняем. А потому, если от физической модели не требуется какой-то особой достоверности или большой предсказуемости — использование параметра drag не лишено смысла.
Rigidbody (Твердое тело)
Твёрдые тела позволяют вашим игровым объектам взаимодействовать с помощью физики. Для реалистичного перемещения твёрдых тел, на последние воздействуют сила вращения и другие силы. Любой игровой объект должен содержать в себе твёрдое тело, чтобы быть подверженным гравитации, действовать согласно назначенным путём скриптинга силам, или взаимодействовать с другими объектами через физический движок NVIDIA PhysX.
Свойства
Свойство: | Функция: |
---|---|
Mass | The mass of the object (in kilograms by default). |
Drag | Какое воздушное сопротивление оказывается на объект пока он перемещается под воздействием этих сил. 0 означает отсутствие сопротивления, а бесконечность (infinity) тут же прекращает перемещение объекта. |
Angular Drag | Какое воздушное сопротивление оказывается на объект пока он вращается под воздействием силы вращения. 0 означает отсутствие сопротивления. Учтите что вы не можете остановить вращение объекта путём установки его углового сопротивления (Angular Drag) в бесконечное (infinity) положение. |
Use Gravity | При включении на объект действует гравитация. |
Is Kinematic | При включении, объект не будет управляться физическим движком, и сможет управляться только при помощи своей трансформации. Полезно при перемещении платформ или если вам необходимо анимировать твёрдое тело, которое имеет назначенный HingeJoint. |
Interpolate | Попробуйте одну из опций если вы замечаете тряску в перемещении своего твёрдого тела. |
— None | Не применено никакой интерполяции. |
— Interpolate | Сглаживание транформации основано на трансформации из предыдущего кадра. |
— Extrapolate | Сглаживание трансформации основано на приблизительной трансформации следующего кадра. |
Collision Detection | Используется для предотвращения проникновения быстро перемещающихся объектов сквозь другие объекты без определения столкновений. |
— Discrete | Use discrete collision detection against all other Colliders in the Scene. Other colliders will use discrete collision detection when testing for collision against it. Used for normal collisions (This is the default value). |
— Continuous | Use Discrete collision detection against dynamic Colliders (with a Rigidbody) and sweep-based continuous collision detection against static Colliders (without a Rigidbody). Rigidbodies set to Continuous Dynamic will use continuous collision detection when testing for collision against this rigidbody. Other rigidbodies will use Discrete Collision detection. Used for objects which the Continuous Dynamic detection needs to collide with. (This has a big impact on physics performance, leave it set to Discrete, if you don’t have issues with collisions of fast objects) |
— Continuous Dynamic | Use sweep-based continuous collision detection against GameOjects set to Continuous and Continuous Dynamic collision. It will also use continuous collision detection against static Colliders (without a Rigidbody). For all other colliders, it uses discrete collision detection. Used for fast moving objects. |
— Continuous Speculative | Use speculative continuous collision detection against Rigidbodies and Colliders. This is also the only CCD mode that you can set kinematic bodies. This method tends to be less expensive than sweep-based continuous collision detection. |
Constraints | Ограничения движения твёрдого тела:- |
— Freeze Position | Выборочно останавливает перемещение твёрдого тела по осям X, Y и Z. |
— Freeze Rotation | Stops the Rigidbody rotating around the local X, Y and Z axes selectively. |
Details
Наибольшее отличие между управлением трансформациями и твёрдыми телами заключается в использовании сил. Твёрдые тела могут управляться силами и вращением, трансформации же не могут. Трансформации можно перемещать и вращать, но это не то же самое, что и использование физики. Вы заметите разницу, когда решите сами испробовать это на деле. Добавление силы/вращения к твёрдому телу позволит изменить позицию и вращение компонента трансформаций (Transform) объекта. Вот почему вам нужно использовать только один из них. Изменение трансформаций при использовании физики может создать проблемы столкновениях и других вычислениях.
Rigidbodies must be explicitly added to your GameObject before they will be affected by the physics engine. You can add a Rigidbody to your selected object from Components->Physics->Rigidbody in the menu. Now your object is physics-ready; it will fall under gravity and can receive forces via scripting, but you may need to add a Collider or a Joint to get it to behave exactly how you want.
Наследование
Когда объект находится под управлением физики, он перемещается частично независимо от своих родителей. Если вы переместите одного из родителей, они потянут за собой Rigidbody потомков. Однако, твёрдые тела также будут падать вниз под воздействием силы тяжести и реагировать на события столкновений.
Скриптинг
Чтобы контролировать свои твёрдые тела, вы будете в основном использовать скрипты для добавления сил и вращения. Вы можете это сделать, вызвав на твёрдом теле (Rigidbody) объекта AddForce() и AddTorque(). Помните что при использовании физики вы не должны напрямую менять трансформацию объекта.
Анимация
For some situations, mainly creating ragdoll effects, it is neccessary to switch control of the object between animations and physics. For this purpose Rigidbodies can be marked isKinematic. While the Rigidbody is marked isKinematic, it will not be affected by collisions, forces, or any other part of the physics system. This means that you will have to control the object by manipulating the Transform component directly. Kinematic Rigidbodies will affect other objects, but they themselves will not be affected by physics. For example, Joints which are attached to Kinematic objects will constrain any other Rigidbodies attached to them and Kinematic Rigidbodies will affect other Rigidbodies through collisions.
Коллайдеры
Коллайдеры это другой тип компонентов, которые должны быть добавлены наряду с твёрдыми телами, чтобы задействовать столкновения. Если два твёрдых тела врезаются друг в друга, физический движок не будет просчитывать столкновение, пока к обоим объектам не будет назначен коллайдер. Твёрдые тела не имеющие коллайдеров будут просто проходить сквозь друг друга при просчёте столкновений.
Colliders define the physical boundaries of a Rigidbody
Добавьте коллайдер при помощи меню Component->Physics. Посетите страницу руководства компонентов для получения дополнительной информации по каждому конкретному коллайдеру:
Составные коллайдеры
Compound Colliders are combinations of primitive Colliders, collectively acting as a single Rigidbody. They come in handy when you have a model that would be too complex or costly in terms of performance to simulate exactly, and want to simulate the collision of the shape in an optimal way using simple approximations. To create a Compound Collider, create child objects of your colliding object, then add a Collider component to each child object. This allows you to position, rotate, and scale each Collider easily and independently of one another. You can build your compound collider out of a number of primitive colliders and/or convex mesh colliders.
A real-world Compound Collider setup
На картинке сверху, игровой объект Gun Model с назначенным твёрдым телом и несколькими примитивными коллайдерами в качестве потомков игрового объекта. При движении Rigidbody родителя под воздействием сил, потомки коллайдеры будут двигаться вместе с ним в том же направлении. Примитивные коллайдеры будут сталкиваться с меш коллайдерами окружающей среды, и родительский Rigidbody изменит способ своего перемещения, основываясь на силах, применённых к нему и том, как его потомки коллайдеры взаимодействуют с другими коллайдерами в сцене.
Меш коллайдеры не могут нормально сталкиваться друг с другом. Если меш коллайдер помечен как Convex, тогда он может сталкиваться с другим меш коллайдером. Обычным выходом из ситуации будет использование примитивных коллайдеров для любых движущихся объектов, и меш коллайдеров для статичных второстепенных объектов.
Note: Compound colliders return individual callbacks for each collider collision pair when using Collision Callbacks.
Непрерывное обнаружение столкновений
Continuous collision detection is a feature to prevent fast-moving colliders from passing each other. This may happen when using normal (Discrete) collision detection, when an object is one side of a collider in one frame, and already passed the collider in the next frame. To solve this, you can enable continuous collision detection on the rigidbody of the fast-moving object. Set the collision detection mode to Continuous to prevent the rigidbody from passing through any static (ie, non-rigidbody) MeshColliders. Set it to Continuous Dynamic to also prevent the rigidbody from passing through any other supported rigidbodies with collision detection mode set to Continuous or Continuous Dynamic. Continuous collision detection is supported for Box-, Sphere- and CapsuleColliders. Note that continuous collision detection is intended as a safety net to catch collisions in cases where objects would otherwise pass through each other, but will not deliver physically accurate collision results, so you might still consider decreasing the fixed Time step value in the TimeManager inspector to make the simulation more precise, if you run into problems with fast moving objects.
Используйте правильный размер
If you are modeling a human make sure the model is around 2 meters tall in Unity. To check if your object has the right size compare it to the default cube. You can create a cube using GameObject > 3D Object > Cube. The cube’s height will be exactly 1 meter, so your human should be twice as tall.
If you aren’t able to adjust the mesh itself, you can change the uniform scale of a particular mesh asset by selecting it in Project View and choosing Assets->Import Settings… from the menu. Here, you can change the scale and re-import your mesh.
Если в вашей игре необходимо сделать так, чтобы создавались экземпляры объектов типа GameObject разного размера, будет вполне нормальным изменять значения масштаба осей трансформаций вашего объекта. Плохой стороной этого процесса является то, что физическая симуляция должна брать на себя основную часть работы во время создания экземпляров объекта, а это в свою очередь может сказаться на снижении производительности в вашей игре. Но это не ужасная потеря, и это не так уж эффективно как при использовании для масштабирования ваших объектов двух других опций. Также не забывайте о том, что неравномерное масштабирование может привести к непредсказуемому поведению при использовании наследования. Поэтому, в таких случаях лучше в своём пакете трёхмерного моделирования изначально создавать свои объекты в правильном масштабе.
Советы
2018–10–12 Page amended
Continuous Speculative collision detection method added in 2018.3
Rigidbody
Rigidbodies enable your GameObjects to act under the control of physics. The Rigidbody can receive forces and torque to make your objects move in a realistic way. Any GameObject must contain a Rigidbody to be influenced by gravity, act under added forces via scripting, or interact with other objects through the NVIDIA PhysX physics engine.
Properties
Details
The biggest difference between manipulating the Transform versus the Rigidbody is the use of forces. Rigidbodies can receive forces and torque, but Transforms cannot. Transforms can be translated and rotated, but this is not the same as using physics. You’ll notice the distinct difference when you try it for yourself. Adding forces/torque to the Rigidbody will actually change the object’s position and rotation of the Transform component. This is why you should only be using one or the other. Changing the Transform while using physics could cause problems with collisions and other calculations.
Rigidbodies must be explicitly added to your GameObject before they will be affected by the physics engine. You can add a Rigidbody to your selected object from Components->Physics->Rigidbody in the menu. Now your object is physics-ready; it will fall under gravity and can receive forces via scripting, but you may need to add a Collider or a Joint to get it to behave exactly how you want.
Parenting
When an object is under physics control, it moves semi-independently of the way its transform parents move. If you move any parents, they will pull the Rigidbody child along with them. However, the Rigidbodies will still fall down due to gravity and react to collision events.
Scripting
To control your Rigidbodies, you will primarily use scripts to add forces or torque. You do this by calling AddForce() and AddTorque() on the object’s Rigidbody. Remember that you shouldn’t be directly altering the object’s Transform when you are using physics.
Animation
Colliders
Colliders are another kind of component that must be added alongside the Rigidbody in order to allow collisions to occur. If two Rigidbodies bump into each other, the physics engine will not calculate a collision unless both objects also have a Collider attached. Collider-less Rigidbodies will simply pass through each other during physics simulation.
Colliders define the physical boundaries of a Rigidbody
Add a Collider with the Component->Physics menu. View the Component Reference page of any individual Collider for more specific information:
Compound Colliders
Compound Colliders are combinations of primitive Colliders, collectively acting as a single Collider. They come in handy when you have a model that would be too complex or costly in terms of performance to simulate exactly, and want to simulate the collision of the shape in an optimal way using simple approximations. To create a Compound Collider, create child objects of your colliding object, then add a Collider component to each child object. This allows you to position, rotate, and scale each Collider easily and independently of one another. You can build your compound collider out of a number of primitive colliders and/or convex mesh colliders.
A real-world Compound Collider setup
In the above picture, the Gun Model GameObject has a Rigidbody attached, and multiple primitive Colliders as child GameObjects. When the Rigidbody parent is moved around by forces, the child Colliders move along with it. The primitive Colliders will collide with the environment’s Mesh Collider, and the parent Rigidbody will alter the way it moves based on forces being applied to it and how its child Colliders interact with other Colliders in the Scene.
Continuous Collision Detection
Use the right size
If you aren’t able to adjust the mesh itself, you can change the uniform scale of a particular mesh asset by selecting it in Project View and choosing Assets->Import Settings… from the menu. Here, you can change the scale and re-import your mesh.
If your game requires that your GameObject needs to be instantiated at different scales, it is okay to adjust the values of your Transform’s scale axes. The downside is that the physics simulation must do more work at the time the object is instantiated, and could cause a performance drop in your game. This isn’t a terrible loss, but it is not as efficient as finalizing your scale with the other two options. Also keep in mind that non-uniform scales can create undesirable behaviors when Parenting is used. For these reasons it is always optimal to create your object at the correct scale in your modeling application.