Search Unity

Physics behind an open parachute.

Discussion in 'Physics' started by hedgeh0g, Mar 1, 2018.

  1. hedgeh0g

    hedgeh0g

    Joined:
    Jul 18, 2014
    Posts:
    102
    Hello,

    I'm making a 2D game where the player chooses direction and "power" so the main character jumps off the ledge following that direction and intensity so:

    Code (CSharp):
    1. rigidBody.AddForce (dir * p, ForceMode2D.Impulse);
    At some point, the player can open the parachute and thus slowdown the fall.

    Now, when a body is skydiving with the parachute open the air causes a resistance that can be reassumed in this formula:

    Code (CSharp):
    1. _airResistance = ((_airDensity * _drag * _area)/2) * (_velocity)^2;
    Where: _airDensity is the air's density which depends on the altitude. _drag can be an arbitrary value (?) which depends on wheter the parachute is open or not. _area is the area of the actual parachute. For the sake of simplicity I've shortened the formula in:

    Code (CSharp):
    1. float r = (_allResistance / 2) * (rb.velocity.y * rb.velocity.y);
    In conclusion, on my Update():

    Code (CSharp):
    1. void Update()
    2.  
    3. {
    4.             float r = (petalResistance / 2) * (rb.velocity.y * rb.velocity.y);
    5.  
    6.             Vector2 resistance = new Vector2 (0.0f, r);
    7.  
    8.             rb.AddForce (resistance, ForceMode2D.Force);
    9.  
    10. }
    This code works fine when the main character's rigidbody is starting to descend, but if the player opens the parachute as soon as he jumps and with a pretty high strenght the character BURSTS towards the sky to the infinite and beyond.

    I'm perfectly fine if the main character goes upward at some point due to an updraft current (which I will include) but why that sudden burst? Is something wrong with my formula or should I cap something?

    Thanks in advance.
     
  2. StickyHoneybuns

    StickyHoneybuns

    Joined:
    Jan 16, 2018
    Posts:
    207
    So there are two variables that you don't explain or show what they are so my answer will have to exclude those. But, I can almost guarantee that it is due to the rb.velocity.y^2. You need rb.velocity.y^2 but you forgot to keep the sign of your force. So no matter which direction the object is falling you have the same amount of force acting on it given the same variables. When moving upwards you need to have a negative force, when moving downwards you need to have a positive force due to the parachute. Because rb is squared you always have a positive force. This is assuming petalResistance isn't keeping your sign.

    So if you need to conserve the sign just simply add this:
    Code (CSharp):
    1. float r = (petalResistance/2)* (rb.velocity.y*rb.velocity.y) * Mathf.Sign(rb.velocity.y);
    Hopefully this works, if not just let us know.
     
    hedgeh0g likes this.
  3. hedgeh0g

    hedgeh0g

    Joined:
    Jul 18, 2014
    Posts:
    102
    Ok sorry, I missed that petalResistance explanations. It is an arbitrary number made of (_airDensity * _drag * _area). Take it as the resistance which the parachute applies while it is open and the character is falling.

    Thanks for your help because it works, I did two mistakes: I was not keeping the sign of my force just like you said. Second, that petalResistance was positive, while it has to be negative.

    Could you please explain me why? I mean, if a rigidbody is in mid-air, gravity will try to slam it to the ground so: -g. However, jumping creates an impulse of force which will (for a brief time) overcome gravity, so: +j. Opening a parachute while falling should create a sort of drag that would slow you down so I thought that the value coming from:

    Code (CSharp):
    1. (_airDensity * _drag * _area) // or simply "petalResistance"
    should be positive, but looks like it has to be negative. Why?

    Thanks again for your help.
     
  4. StickyHoneybuns

    StickyHoneybuns

    Joined:
    Jan 16, 2018
    Posts:
    207
    So, now that I know what petalResistance is, my code is actually wrong. _drag is the Vector that should have the direction. It's really simple and you already corrected it by making _drag negative. _drag is not always negative. _drag is a Vector that is always opposite of velocity. So therefore we can just tell _drag to be the opposite of velocity like this.

    Code (CSharp):
    1. _drag = -_drag*Mathf.Sign(rb.velocity.y);
    2. petalResistance = (_airDensity * _drag * _area);
    3. float r = (petalResistance/2)* (rb.velocity.y*rb.velocity.y)
    Again, you already did this but this is actually a more correct/cleaner method, so no need to change it unless you want to.

    I attached a neat little vector diagram just for show and tell.

    Also, yes for real life applications _drag of the parachute would almost always be a positive/upward force. Why? Because humans in real life don't jump upwards then pull a parachute immediately, or if they do the result is insignificant. However in the game you have and exponential force upwards that gets called again when the parachute is opened. Since you took drag out of the air resistance formula you just account for it in the parachute formula.
     

    Attached Files:

    Last edited: Mar 1, 2018
    hedgeh0g likes this.
  5. Todd-Wasson

    Todd-Wasson

    Joined:
    Aug 7, 2014
    Posts:
    1,079
    While you're at it, make sure it's done in FixedUpdate(), not Update().
     
    hedgeh0g likes this.
  6. EthanF4D

    EthanF4D

    Joined:
    Jan 9, 2018
    Posts:
    13
    the “air resistance drag” is always opposite to velocity like you said. You should use the whole vector not just the y component of it.

    Code (CSharp):
    1. float _airResistance = _open * ((_airDensity * _area)/2) * (rb.velocity.sqrMagnitide);
    2. Vector2 _dragForce = _airResistance * -rb.velocity.normalized;
    3. rb.AddForce(_dragForce, ForceMode2D.Force);
    However, rigidbody.drag already does all that calculations. You dont have to calculate by yourself. Use a script to increase the drag value to say 10 when parachute is opened and 0 when it is closed
     
  7. Todd-Wasson

    Todd-Wasson

    Joined:
    Aug 7, 2014
    Posts:
    1,079
    rigidbody.drag is at the center of mass so it won't produce any torque. Not a good way to do parachutes imo.
     
  8. EthanF4D

    EthanF4D

    Joined:
    Jan 9, 2018
    Posts:
    13
    I get your point. For the “torque”,
    1. if you want to fake it, you can still use rigidbody.drag/angularDrag and then use a script to AddTorque() that would rotate it downwards in FixedUpdate(). You might want to set rigidbody.centerOfMass to nearer the parachute to make it more like pivot.

    2. Seperate the parachute and the load, parachute has larger mass/drag/angularDrag and the load has less. Then use hinge joints (or chains of character joints, basically a rope) to connect them.

    I have tried 1. But not 2.
     
  9. Todd-Wasson

    Todd-Wasson

    Joined:
    Aug 7, 2014
    Posts:
    1,079
    I'd just make it physically correct and call it a day. It's not hard. Just apply the force at the center of the parachute opposite to that point's velocity vector and call it done. The rotation will be consistent and correct without trying to fiddle with angular drag and other such things that have nothing to do with the dynamics of interest here. :p