- Home /
[Closed] Is there a way to simulate axial drag on a Rigidbody?
If I made a model which is a flat surface, like a wing. How can I make it behave so the drag only affects it when you push it with the flat surface facing the direction it's going?
I have made a sketch in hope of having you understand it better.
Fellow members of unity, I am begging for an answer. I have pursued this very topic for weeks. I have searched and looked in every thinkable thread and forum post according to this issue. Is any soul ever going to take a wild leap into the gloomy darkness and save me from the malicious state of having no wings? I wish to soar in the world of unity with this vessel I am modeling here. But with no wings, I'm afraid it's nothing but a dream... Oh, the humanity! overkill drama ftw
Answer by robertbu · Aug 17, 2013 at 10:05 PM
You don't have any code specifics here, but let me make an untested suggestion for an approximation. First you have a wind direction. If this is an airplane part, it may just be the negated value of the direction of the plane. However you get it, you will have a vector representing the speed and direction of the wind that could influence this control structure. The control structure will have a normal to the surface. Depending on how you modeled this structure, it will be something like transform.up or transform.forward for the world version of this normal. To vary the amount of force that is applied you can do:
forceToApply = Mathf.Abs(Vector3.Dot(windVector, surfaceNormal)) * someFactor;
When control structure is parallel to the wind (i.e. the normal and the wind direction is perpendicular), no force will be applied. When the control structure is perpendicular to the wind (i.e. the normal aligns either positively or negatively with the wind), then the amount of force will be the velocity of the wind times some factor. And you will see fractional values between no force and full force as the control structure is rotated..
For a given rotation, this equation produces a linear increase in force as the velocity of the wind increases. Real drag goes up as the square of the velocity. I'm not sure of your goal here (or if it is even achievable with Unity's physics engine), but you might get a somewhat better approximation by:
forceToApply = Mathf.Abs(Vector3.Dot(windVector.normalized, surfaceNormal));
forceToApply = forceToApply * windVector.normalized * windVector.sqrMagnitude * someFactor;
Again this is game-type approximation without knowing your goal or studying equations for drag.
Well. I am more of an artist. And I am best at setting things up in unity if I have the materials infront of me. But I think this information will be enough for my fellow coder, and he can probably make something out of it... If he is awake.
I have initially thought of a script that I will add to separate invisible gameobjects in which I will attach on the wings of the model through joints. Because the aircraft model itself will be a physical rigidbody. And those will provide lift when I start accelerating the vessel through the air.
Rob, we kind of got the script-thingy you wrote. But my coder couldn't figure it out. We even tried something that would probably work by applying force in the opposite direction when a normal (y in this case) is facing the direction it is going. But no luck...
Here is the script btw, and it does not work.
#pragma strict
var multiplier: float = 5;
private var lastY: float;
//just a script that reads how fast an object travels on it's Y-axis.
//and then read the velocity it goes, take that velocity and make an
//opposite force on it's Y-axis, but in the opposite direction.
function Update () {
if(lastY != 0.0000){
var difference: float = lastY - transform.localPosition.y;
rigidbody.AddForce(0, -difference * multiplier, 0);
}
}
function LateUpdate () {
lastY = transform.localPosition.y;
}
Does anyone have an idea? I mean, I have seen this been achieved in $$anonymous$$erbal Space Program (A popular Unity game), where they have attachable wings that does provide aerodynamic stability.
So it should be possible.
For games like these, you don't know how much of the action is done through the Physics engine, and how much is "faked" through calculation. I though your original question was about "flaps" and how to calculate the force differences depending on the angle of the flaps. But you don't really have to calculate and apply real forces. You can gather the angle of the flaps and then calculate what what the plane should be doing. Then you could make it happen without physics.
As for getting you flying. Here is a quick script to get you in the air. It allows you to take off and then cut the throttle to maintain altitude. It rotates the plane around its axis (no force). It looks strange because the plane does not bank, but if you were to add banking and momentum to the turn, it would look a lot more realistic.
To make this work:
Add a rigidbody to your plane (if you don't already have one).
Given the plane and the ground 'ice' for the physic material.
Set the Drag in the Rigidbody to 0.75.
Set the mass to 1.0.
Attach the this script:
pragma strict
var throttle = 0.0; var throttleDelta = 1.0; var thrust = 2500; var lift = 1.0; var rotationSpeed = 30;
function Update () { throttle += Input.GetAxis("Vertical") throttleDelta Time.deltaTime; throttle = $$anonymous$$athf.Clamp01(throttle);
transform.Rotate(0.0, rotationSpeed * Input.GetAxis("Horizontal") * Time.deltaTime, 0.0); } function FixedUpdate() { Debug.Log(transform.forward * thrust * throttle); rigidbody.AddForce(transform.forward * thrust * throttle); var v = rigidbody.velocity; v.y = 0.0; rigidbody.AddForce(Vector3.up * v.magnitude * lift); } function OnGUI() { var v = rigidbody.velocity; v.y = 0; GUI.Label(Rect(20,20,150, 50), "Throttle: "+throttle * 100+"%"); GUI.Label(Rect(20,70,150, 50), "Speed: "+v.magnitude); GUI.Label(Rect(20,120,150, 50), "Altitude: "+transform.position.y); }
'Vertical' controls the throttle. I used the arrow keys on my machine. 'Horizontal' turns. It takes 100% throttle to take off, and it cruses at altitude at around %75 throttle.
Note this is a very simple script. $$anonymous$$ajor flight games have 1000s of lines of code (maybe more) implementing the flight mechanics of a plane.
We are getting a long way from the original questions which (to me) was about flaps. It may be time to redefine what technical problem you are trying to solve and post a new question.
Answer by weenchehawk · Aug 18, 2013 at 07:46 PM
Perhaps I'm not understanding your problem correctly but the answer seems fairly straightforward . . .
1) Set the drag (coefficient) on your objects rigidbody to 0 to eliminate it from the problem
2) Create a Script called Drag that looks something like the below & attach it to your object. Every frame it will apply a force in opposition to & in proportion to the velocity the object is moving in. To eliminate an axis, set it to 0 in the AxisDrag, to reduce the drag on an axis, reduce it's axis value in . . . yeah you get the idea.
class Drag : MonoBehaviour
{
public Vector3 AxisDrag;
public Update()
{
ApplyForce(rigidbody.velocity.x * AxisDrag.x * -1 * Time.deltaTime);
ApplyForce(rigidbody.velocity.y * AxisDrag.y * -1 * Time.deltaTime);
ApplyForce(rigidbody.velocity.z * AxisDrag.z * -1 * Time.deltaTime);
}
}
You'll likely need to bring the mass of the object into the equation if it's mass is not equal to 1, and you'll need to tweak the Axes somewhat, you may also need a general coefficient of drag to adjust your values depending on how Force affects velocity/acceleration in unity (in the real world it's force = mass * acceleration)
Oh yeah I haven't given it the necessary brain cycles but it might also work as the simple product of teh two vectors -1 Time.deltaTime. Which reminds me the syntax isn't tested but armed with the general principle the rest should be able to be figured out from here.
In fact now that I see you need this for a flight / win simulator you probably want to connect AxisDrag to some kind of Wind Direction vector. Or create a wind object / script that adjusts it's direction in time for variable / gusts / blusters, and then simply connect the AxisDrag in this script to the wind direction and apply those normalised forces (times a coefficient) to your object.
Well, your method didn't work either. Well, partially because my coder had to change some errors in your initial script to make it work. And what the script did, which is exactly what it did before, is putting global Y-axis drag on the object when it should act on local Y-axis drag.
Here is the code my coder made.
#pragma strict
var AxisDrag: Vector3;//multiplier
function Update () {
var x: float = rigidbody.velocity.x * AxisDrag.x * -1 * Time.deltaTime;
var y: float = rigidbody.velocity.y * AxisDrag.y * -1 * Time.deltaTime;
var z: float = rigidbody.velocity.z * AxisDrag.z * -1 * Time.deltaTime;
rigidbody.AddForce(x,y,z);
}
You need to calculate and apply the aerodynamic effect on it.
Yes, the code I provided was to demonstrate a principle and your developer seems to have implemented it well. Incidentally 30000 is a lot of drag, it might be enough drag to make something go directly downwards, this applies 30000 x the velocity in that direction units of force. I was thinking somewhere between 0.5 & 1.5 - give that a go & let me know how it works.
Also looking at your picture which is quite helpful are you expecting the object to follow the direction of the long blue curved path towards the ground (assume so) or away from the ground ? The reason I ask is that this arrow is not the natural path of an object with only gravity & air resistance acting upon it.
Well, I expect it to go along that blue, diagonal path because of how the object is rotated. Because the object's Y-axis (green arrow) is projecting away from the same side as the flat surface. So realisticly, it is going to behave like a wing where the Y-axis drag acts upon the wing so it will glide along that blue path. As I have tried to explain in this thread.