Is is the Reynolds number or something arbitrary in PhysX? I can’t find any info on it, besides “it’s drag”. What I’m mostly seeking is information on the formula by which it affects the velocity of the rigidbody.
I’m pretty curious about this as well. Seems like a Cd would have been most useful number for most of to use but realistic Cd numbers produce way too much drag. I’m really frustrated with Unity’s refusal to commit to Units (lol, so to speak). I assume the devs don’t want to label units because they are afraid of scaring people? As it is I’m forced to create a virtual lab as a development tool to try and figure out what in the flying @$* I’m working with here. People who just want to tweak until it looks right can still do that just fine with labeled units.
…My other concern is that it looks like scaling objects effects some (but not all) physics calculations which complicates matters even more.
I’m guessing force numbers are in newtons; anyone figure out angular drive force? I would have expected it to be newton meters but it doesn’t look right so far. Now that I think about i, my first round of testing seemed to indicate that “force” definitely was not Newtons but I’d like to believe I had a scaled transform throwing the measurement off.
According to my experiments all force/mass numbers are standard metric, (Nm, kg, m). Launching an object with mass 1 with a (ForceMode.Impulse) force of 10 will give it a velocity of 10. All of those make sense and are as per the PhysX API specs.
What I’m not clear on is what drag is indicative of. I’ve done in-engine experiments vs graph simulations and drag in unity and drag in simulations do not seem to match up. Calculating Vt does not seem to work as expected either.
I’d just like to know, is it an arbitrary dimensionless value? If so, fine, I can deal with it, as long as there is a formula for its interaction with the physx world. It would just be good to know.
The way I think about it is the factor in which the object is able to push the air away. The faster the object is travelling, the easier it moves, however, the coefficient plays a much larger role in the behaviour. This is perhaps not the greatest explanation, but it’s my best.
I worked out that angular velocity (or torque) is in radians per second. I don’t like it how the real names of the parameters are replaced with simpler names, and seemingly in rare events simpler units. For example “Bounciness” is the Coefficient of Restitution.
From my experiments there is some reason to the effect of D on forward velocity, but it does not seem to add up any basic deceleration formula that I can discern.
There should be a law that forces platform developers to document the units of the values they come up with
I’m also very frustrated by this not knowing what kind of values are expected…
I’m under the impression that integration might be done like this:
Drag is defined as a force exponentially linked to velocity, that is in the opposite direction of velocity. I don’t know of the PhysX implementation, but typical quadratic drag goes like this…
dragForceMagnitude = velocity.magnitude ^ 2 * drag; // The variable you’re talking about
dragForceVector = dragForceMagnitude * -velocity.normalized;
Oddly shaped objects with big flat surfaces hitting the air have a high drag coefficient. At low velocities, your drag coefficient becomes quite pointless.
I guess the best thing to do would be to manually integrate drag in, instead of relying on PhysX’s unknown implementation… We have to do it if we want accurate gravity, why not for drag also?
Thanks for that snippet!! It’ll surely come in handy here
For a more realistic approach, it should be interesting to set up a ‘least drag’ direction vector, and interpolate from that and maximum drag based on the object’s velocity in relation to that vector… this would enable for instance, simulating a skydiver, which has a higher terminal velocity when he’s going head first, and more drag when he spreads out.
More realistic than that would involve actually simulating air flow and displacement… and we’d need a fluid dynamics engine instead of a rigidbody physics one
Eh, to be honest I wouldn’t bother. The quadratic drag formula I gave is itself a simplified version and PhysX likely uses it (or something slightly better). You have to realize that drag is a very complex phenomena. My friend who is an aeronautical engineer has modeled programs that go on for days to simulate drag in fluids ‘accurately’ and even those are approximations!
Yeah, but I’d rather do it myself than work with unkown units and their unknown relations… especially when having control of what’s going on is important, like in a flight sim.
And yeah, realistic drag is a subject for several books and master’s degrees… and it requires modelling fluids instead of just rigidbodies and forces… hence my ‘least drag vector’ idea.
As an evolution of that, one might go as far as creating different drag values for each axis, as in, forwardFacingDrag, LeftFacingDrag, and so on… I guess that’s about as far as one can go before one’s sanity is brought into question…
@andorov
That’s the formula I’ve been using, though it’s all about velocity. Factoring forces would require mass to be a variable, and it doesn’t figure in drag in PhysX afaict. It’s limited, but for a simple simulation like this it should be giving fairly predictable results. Problem is it’s not doing that beyond certain distances (1000 meters or so) and certain velocities (>150m/s).
@HarvesteR
The way I’ve used to make simple flight dynamic simulations in Unity (and my own Havok powered engine), is use local forces. Unity offers ConstantForce which works ok. AddForceAtPosition can give you angular influences as well, simulating control surfaces.
If you are looking at having more control over the physics simulation I’d look into integrating an already existing one, such as Havok or the complete PhysX binding. Both are available to hobbyists. Bullet is another decent physics lib, and has a (untested by me) CLI wrapper in bulletsharp.
None of these are trivial, but almost certainly better in the long run than rolling your own.
That’s a unity pro feature so not open to me yet.
Thanks for the input guys. I’ll keep plugging at it and let you know if I get it going.
For my vehicles (boats, planes) I use my own drag, and set the in-game drag to zero… However angular drag is another matter as it seems remarkably more complex to model accurately. In order to get realistic-but-playable flight physics I had to link the angular drag value to the velocity of the plane, otherwise a slight touch on the control sends the plane spinning.
I am pretty annoyed that there is no information forthcoming about what the drag values actually do to the rigidbody… obviously they act opposite to the velocity (angular or otherwise)… but it would be nice to have the equation.
Also I believe there is a bug with the angularDrag as it takes a fraction of a second to “kick-in”. No matter what value it is set at, I always have freedom to roll the plane without angularDrag for the first few frames. This creates a really annoying effect where rotations seemingly slow-down for no reason.
I guess this is because the rigidbody’s angular velocity is unreliable?
Here was something I posted some time ago, should be helpful. Unity does commit to units by default, but it doesn’t shoehorn you in, because the math doesn’t care. By default 1 unit = 1 meter, so that standard m/s m/s^2… type stuff works. If you’re working in imperial, or your model scales are out, then you need to adjust.
Drag is just a measure of how much velocity is lost per tick. You can use the post below to implement terminal velocity/acceleration dynamics for controlling vehicles.
Not to nitpick, but velocity.sqrMagnitude would be faster, since the engine uses the square root to compute the velocity. taking that and squaring it again is just doubling effort.
This thread is a bit old, but for reference, the drag field in Rigidbody sets the linearDamping into PhysX actor, so the factor is linear. If you want to implement aerodynamics drag you should apply the force youself.
i have used this, its quite similar to the box2d drag that unity uses in 2d physics
float c = timestep
vector v = current velocity (as in objects current velocity + gravity * timestep)
float dt = linearDrag
vector nv = v * 1 / (1 + c * dt) = new velocity
i have used this thing in trajectory prediction and it works quite well.
Drag reduces the velocity by a “fix” percentage based on the current fixedDeltaTime and drag value
If the drag value equals or is greater than the fixed frame rate (1/fixedDeltaTime) the rigidbody can’t move on it’s own.
Since collisions are calculated / applied after the drag, they can cause an impuls spike in velocity and movement, but the next fixed frame the velocity will be 0 again unless there are consequential collisions which again apply an impule force. Note: as long as a collision is “active” (as long as collision stay is called) there might be forces applied from the colliding rigidbody. However all momentum that got tranferred will completely vanish the next frame.
Example: If you have set your fixedDeltaTime to 0.01 you will get 100 FixedUpdates per second. If you set the drag value to 50 and initial velocity of 100 will be cut in half each fixed frame because the “percentage multiplier” is (1 - (0.01 * 50)) == 0.5
If the drag is 100 or greater the multiplier will be 0 ( == 1 - (0.01*100)). Keep in mind that the default setting for the fixedDeltaTime is 0.02 which gives you a max drag of 50
I haven’t tested when and how Joints apply their forces. If they use the “normal” AddForce mechanics the drag could draw the Joint completely useless. If it’s appllied internally after the drag it might have an affect. But keep in mind that no velocity will survive the next frame if your drag >= 1 / fixedDeltaTime
Conclusion: That’s simply a strange approach. I’m not sure if this was different in the past, but anyways the “hint” on the drag field is clearly wrong since a range of (0 to infinity) makes no sense. The manual states the same, so i guess they wanted to do something like HarvesteR suggested as the second example: