📜 ⬆️ ⬇️

How Drag works in Unity physics

Realizing that my articles are like the delight of a person who first saw some (many have long been familiar) thing, he decided to write another one. The reason is the drag parameter of the Rigidbody component that interests me. Explanations and, moreover, formulas - how it works - do not provide guidance. Therefore, you will have to understand yourself.

If someone is too lazy to read, you can scroll down to where the found algorithm is found for how slowing works with Unity in Unity.

When you get acquainted with physics in Unity, the first thing that is taught is that Rigidbody is the embodiment of the physical properties of an object. He has a couple of parameters that define his interaction with the outside world. Actually, the most significant for dynamic objects: mass . Everything is intuitively clear with her: Newton's law and all that ... They applied force briefly - they received a pulse and, accordingly, changed the speed of the object. We put a long time: we get the acceleration depending on the mass.

In addition, Rigidbody has an interesting parameter - drag . In the words of the developers: the drag parameter sets the drag object. In their language, drag is slowing down, braking. No other explanation is given. Speaking of physics and braking, something comes to mind from ballistics (aerodynamics, hydrodynamics, etc.). Perhaps drag is a factor proportional to the square of the speed. That would be reasonable. But.
')
Simple experience shows that in Unity, bodies with a high drag value do not move at all. Gravity does not affect them, it is impossible to push them. But at the same time they are, that is, the square of their speed is zero. So everything is not so simple ... or, on the contrary, not everything is so difficult. Physics in computer games should be calculated quickly, which means that simplifications regarding the real physical model are possible. Although it would be fun to implement the game with, say, relativistic effects ...

The first question I asked was: at least the mass in Unity behaves like a mass? The experiment showed that - yes.

Mass / Gravity Check
To begin with, in a simple scene, I launched a ball with a mass of 1 from a height of 5 meters per plane. The trigger on the plane stopped the timer, so that I could observe the time when the ball fell.

image

The estimated fall time for it should be: t = sqrt (2 * h / g ), where h is the height, g is the acceleration of gravity. In our case ( h = 5m, g = 9.81m / s ^ 2) t ≈ 1.0096.
The launch showed a value of 1.02, which is close to the desired.

image

Built-in gravity is good. I would like to check if she is cheating? Turning off gravity for Rigidbody and instead manually creating the current force:

void FixedUpdate() { rb.AddForce(0, -9.81f, 0); } 

The result was the same ( t = 1.02). Not bad.

For the acting force, several different values ​​were then used. And always the change in the acting force ( rb.AddForce (0, xxx , 0); ) caused a change in the “fall” time, which coincides with the calculated one. So the model of interaction of forces and mass turned out to be quite familiar, Newtonian.

Next, to test and compare the built-in physics engine and the simulated one, I created two balls. One moved under the influence of gravity, the other under the action of the script. And this time there were no forces. Changes in speed were considered "manually" in the code.

image

For a start, it was worth checking out a simple drop without slowing down ( drag = 0). The code moving the second ball was pretty simple:

 void FixedUpdate() { Vector3 newVelocity = rb.velocity + gForceVector * rb.mass * Time.deltaTime; rb.velocity = newVelocity; } 

rb is a component of the Rigidbody sphere. gForceVector - gravity vector (0, 9.81, 0).

image

So far everything is the same.

Now, increase the left ball drag ( drag = 2). He began to fall more slowly:

image

Interesting fact. Increasing the drag parameter to large values ​​(more than or equal to about 50) resulted in the ball not moving at all. The change in the mass of the object did not affect this fact in any way, which led to the idea that the drag parameter is kinematic, that is, it depends (and affects) position, speed, acceleration, etc., without taking force or momentum into account.

What else could influence the algorithm, where did drag appear? Perhaps the frequency of updating physics. Although this would not mean the best move on the part of the developers. But what the hell is not joking. Let's change the time for updating the physics to 0.005 seconds.

image

Dependence is still there. However, this seems to be a computational error. Further increases in the frequency of updating physics do not significantly change the time of the fall. Which, by the way, means that somewhere in the developers code there should be something like " ... * Time.fixedDeltaTime ".

So, what do we know about the drag parameter? He is kinematic (considered after the action of all forces). It multiplies (although it may not be himself) by Time.fixedDeltaTime and reduces speed. The simplest thing one could think of with such conditions is something like this:

 void FixedUpdate() { Vector3 newVelocity = rb.velocity + gForceVector * rb.mass * Time.deltaTime; newVelocity = newVelocity - newVelocity*myDrag*Time.deltaTime; rb.velocity = newVelocity; } 

The new action looks quite primitive: one multiplication and one subtraction (with the amendment to the fact that actions are carried out with vectors). However, with something you need to start. We check this code, for convenience, automatically assigning the variable myDrag (from the second sphere script) the value of the drag parameter of the first sphere.

drag = 1
image

drag = 3
image

drag = 15
image

drag = 50
image

Actually, here both balls did not start moving. I just got tired of waiting.

So, the result was unexpected for me. The primitive algorithm, which was conceived as a starting point, from which I would further push off - turned out to be an end point. It seems that this is exactly how slowing is considered in Unity using the drag parameter. On the other hand, simpler means faster (in terms of runtime).

Further experiments did not show any discrepancies between my script and the embedded physics. Nearly. There was one little thing. If drag = 100, my second ball, driven by a script, majestically floated upwards.

drag = 100
image

In general, this was to be expected, based on the algorithm. However, in Unity this is not observed. Therefore, we have only one simple modification of the code:

 void FixedUpdate() { Vector3 newVelocity = rb.velocity + gForceVector * rb.mass * Time.deltaTime; newVelocity = newVelocity * Mathf.Clamp01(1f - myDrag*Time.deltaTime); rb.velocity = newVelocity; } 

Now, the “negative” movement is excluded and we have a full-fledged imitation of the action of forces and braking of the Unity engine.

The physical analogue of the drag parameter itself is problematic. One can only say that it determines nonlinear friction (or nonlinear resistance — as convenient as possible). At the same time, the algorithm itself is simple and, probably, quickly executed. Therefore, if a particular reliability or high predictability is not required from the physical model, the use of the drag parameter is meaningless.

Source: https://habr.com/ru/post/318254/


All Articles