Search Unity

Need rigidbody2d.AddExplosionForce

Discussion in '2D' started by LaneMax, Nov 19, 2013.

  1. LaneMax

    LaneMax

    Joined:
    Aug 12, 2013
    Posts:
    181
    Been messing a lot with these 2D features, love them :D! But came something I really need rigidbody2d.AddExplosionForce, it exists within the regular rigidbody but not in the rigidbody2d. Anyone have any ideas, or a away around get this to work? Really hoping they'll add it later.
     
  2. dasbin

    dasbin

    Joined:
    Jan 14, 2012
    Posts:
    253
    Agreed.
    Also missing, and equally as important IMHO, is an equivalent for applying a ForceType, and also applying a rigidbody2d.rotation
    I hope the Rigidbody2D class gets expanded to be as full-featured as the 3D class in short order. In its current state it is useless for my game and we stick with PhysX just because of its feature-completeness.

    Also on the wishlist is the ability to change the axes the entire new 2D system works with. Our game is currently built on the XZ (top-down) not XY axes, which is unchangeable because this is also the only orientation of a NavMesh, AFAIK. Seems like a huge oversight to not have the 2D features compatible with their own NavMesh system.
     
    Last edited: Nov 20, 2013
  3. LaneMax

    LaneMax

    Joined:
    Aug 12, 2013
    Posts:
    181
    Sweet, here's hoping :D
     
  4. dasbin

    dasbin

    Joined:
    Jan 14, 2012
    Posts:
    253
    Cool.
    Who did you contact at support?
    I'd really like to get in touch with them regarding the other missing features mentioned above, and it would be good to know they are going to a willing listener.
     
  5. LaneMax

    LaneMax

    Joined:
    Aug 12, 2013
    Posts:
    181
  6. Swamy

    Swamy

    Joined:
    Feb 12, 2013
    Posts:
    14
    This is the extension script I'm currently using as a workaround. Don't know if that's of any use for you guys:

    Code (csharp):
    1. public static class Rigidbody2DExtension
    2. {
    3.     public static void AddExplosionForce(this Rigidbody2D body, float explosionForce, Vector3 explosionPosition, float explosionRadius)
    4.     {
    5.         var dir = (body.transform.position - explosionPosition);
    6.         float wearoff = 1 - (dir.magnitude / explosionRadius);
    7.         body.AddForce(dir.normalized * explosionForce * wearoff);
    8.     }
    9.  
    10.     public static void AddExplosionForce(this Rigidbody2D body, float explosionForce, Vector3 explosionPosition, float explosionRadius, float upliftModifier)
    11.     {
    12.         var dir = (body.transform.position - explosionPosition);
    13.         float wearoff = 1 - (dir.magnitude / explosionRadius);
    14.         Vector3 baseForce = dir.normalized * explosionForce * wearoff;
    15.         body.AddForce(baseForce);
    16.  
    17.         float upliftWearoff = 1 - upliftModifier / explosionRadius;
    18.         Vector3 upliftForce = Vector2.up * explosionForce * upliftWearoff;
    19.         body.AddForce(upliftForce);
    20.     }
    21. }
     
  7. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    1,964
    I have added a whole bunch of missing methods, unfortunately these didn't make it into the 4.3 release.

    If you are referring to ForceMode type used in the AddForce methods (etc) then this has been added since the 4.3 release.

    Can you not use the Rigidbody2D AddTorque method or just modify the angularVelocity property directly or were you referring to something else?
     
  8. dasbin

    dasbin

    Joined:
    Jan 14, 2012
    Posts:
    253
    Thanks for the reply!

    I was referring to ForceMode; my mistake. And excellent!

    In 3D, rigidbody.rotation sets the rotation (Quanternion) *directly* without force or velocity. It is akin to changing the Transform values, but my understanding is that setting it in rigidbody.rotation doesn't fight the physics step.
    For example, in currently using the 3D physics system, my (2D) player character gets its rotation changed directly to face the user's input direction, but also generally moves and bounces around by forces and interactions in the world. I did try merely setting transform.rotation, but there is a visible "jitter" every frame where the player shakes when he also has an angular velocity from bouncing around the world etc. Rigidbody.rotation eliminates this problem and plays much more nicely with the angular velocities in play. So that's why I'd like to see this method in the 2D rigidbody as well, if possible.

    I'm sure the MoveRotation and MovePosition methods would be similarly useful to others, as well. Those additionally check for collisions between the two positions.
     
    Last edited: Nov 23, 2013
  9. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    1,964
    I'm not sure I appreciate the need for setting the 2D rigid-body directly so it's out of sync with the transform until the next physics update. Either way, setting the rigid-body directly is bad for physics and performance just as setting indirectly via the transform is. It seems like this is just different way of potentially encouraging bad behaviour.

    Unfortunately, this is not true at all. It causes contacts to (eventually) be re-evaluated and has other potential side-effects in Box2D.

    Here's what happens:
    If you change the rigid-body position or rotation (say I expose Rigidbody2D.position and rotation) then any interpolation/extrapolation until the next physic update would have to stop so smooth motion until the next update ceases and if this continually happens then you'll get jitter. If interpolation is off, you'll continue to render at the transform position but that won't match the Rigid-body position. This doesn't provide any benefit I can see.

    So until the next physics update the rigid-body and the transform won't match and it'll render at the current interpolated position or if interpolation is off, it'll render at the rigid-body position *before* you updated it. When the next physics update comes along, the rigid-body change will update the transform or, if interpolation is on, it'll interpolate from the rigid-body position you set to the position the physics system has updated to (assuming it's different).

    Don't get me wrong here though; I'm not trying to be obstructive or anything, my intention is to try to ensure we don't just copy the Physics 3D API into the 2D one blindly as there are a bunch of things that we are considering changing/deprecating later for 3D so we'd like to keep 2D as "clean" as possible. Of course this doesn't mean we should sacrifice useful functionality so If I can fully understand the use-case and it's real, it'll go in.

    Yes and that's coming although it really should only work for kinematic bodies. For dynamic bodies it's terrible for performance and doesn't give the correct behaviour i.e. only kinematic bodies will not be affected by collisions during the move position/rotation.

    With MoveRotation/MovePosition in-place and using a kinematic body you should be good to go.
     
  10. dasbin

    dasbin

    Joined:
    Jan 14, 2012
    Posts:
    253
    Hmm, interesting. All I can do is defend my own usage of the method to which I don't think there is an appropriate way of emulating the behaviour through forces or angular velocity.

    When there is user input in any direction, I quickly (but smoothly) lerp the rotation value of the rigidbody to match and follow the input, so that the player character is pointing in the direction of input.
    When there isn't user input in a direction, then I stop setting the rigidbody.rotation. What happens at that point is a unique behvaviour and why I like to do things this way. Although the rigidbody has been directly pointing in the direction of user input for a while. as soon as I stop setting the rotation directly, there is a continuation of the momentum in angular velocity. In other words, the rigidbody will then have a bit of angular momentum in the direction of something that would have physically caused him to turn a bit a couple seconds ago (ie something hit his side and would have caused him to spin if this hadn't been overcome by rigidbody.rotation). So you see the residual effects of that previous momentum on the rigidbody as soon as direct control is released.

    I know this is probably an edge case, but I do really like the mix of arcade-controls and physical interaction this gives us, and I can't think of any other way it'd be possible. It gives a feeling of being bounced around the world, even though the player always has very direct control of the character.

    What is interesting is that although I am using Interpolation and have a fairly high difference between my physics timestep and actual graphical framerate, I'm not seeing the negative jitter effects on interpolation that you mentioned should be happening. Perhaps because I am only setting the rotation by very small (lerped) amounts each frame.


    On a philosophical note: You can disallow something because it is a bad idea programatically, but that doesn't mean it is a bad idea for the game. An improper usage might be the only way to achieve a great game in some circumstances!
     
    Last edited: Nov 23, 2013
  11. _Acid_

    _Acid_

    Joined:
    Jul 26, 2013
    Posts:
    9
    MoveRotation is indeed very important. I have a ship that should be turned in the direction where the joystick is pushed.

    With 3D rigidbody it is done like this:

    targetAngle = Mathf.Rad2Deg * Mathf.Atan2(controlAxis2.y, controlAxis2.x) + 90f;

    //Move object angle towards target angle using linear interpolation
    currentAngle = Mathf.LerpAngle(currentAngle, targetAngle, rotationDamping/2 * Time.fixedDeltaTime);

    //Rotate object using physics handled MoveRotation
    rigidbody.MoveRotation(Quaternion.Euler(new Vector3(0f,currentAngle, 0f)));


    This is a top-down shooter, so it is the y-value that is rotated...

    But how on earth could that be done with AddTorque only?
     
    Last edited: Jan 18, 2014
  12. Mario-M701

    Mario-M701

    Joined:
    Feb 15, 2014
    Posts:
    2
    Thank you Swamy!!
    I also missed this feature, and your workaround just works perfect.
     
  13. iftah

    iftah

    Joined:
    Feb 25, 2014
    Posts:
    8
    Can you please post an extension for Rigidbody2D.MovePosition? Thank you
     
  14. tomandjerry-tas

    tomandjerry-tas

    Joined:
    Feb 7, 2013
    Posts:
    23
    perfect ...... Thank you :):):)
     
  15. renedon

    renedon

    Joined:
    Jul 14, 2017
    Posts:
    3
    Perfect, thanks!
     
  16. Merrick20

    Merrick20

    Joined:
    Feb 20, 2015
    Posts:
    3
    I just logged in liked your reply and needed to say this was amazingly useful for me as I needed it for my game desperately.
     
  17. MaDDoX

    MaDDoX

    Joined:
    Nov 10, 2009
    Posts:
    754
    Minor improvement to Swamy's excellent snippet, preventing attraction/negative explosion forces from happening, when radius is small:

    Code (csharp):
    1.  
    2. public static class Rigidbody2DExtension
    3. {
    4.     public static void AddExplosionForce(this Rigidbody2D body, float explosionForce, Vector3 explosionPosition, float explosionRadius)
    5.     {
    6.         var dir = (body.transform.position - explosionPosition);
    7.         float wearoff = 1 - (dir.magnitude / explosionRadius);
    8.         body.AddForce(dir.normalized * (wearoff <= 0f ? 0f : explosionForce) * wearoff);
    9.     }
    10.  
    11.     public static void AddExplosionForce(this Rigidbody2D body, float explosionForce, Vector3 explosionPosition, float explosionRadius, float upliftModifier)
    12.     {
    13.         var dir = (body.transform.position - explosionPosition);
    14.         float wearoff = 1 - (dir.magnitude / explosionRadius);
    15.         Vector3 baseForce = dir.normalized * (wearoff <= 0f ? 0f : explosionForce) * wearoff;
    16.         body.AddForce(baseForce);
    17.  
    18.         float upliftWearoff = 1 - upliftModifier / explosionRadius;
    19.         Vector3 upliftForce = Vector2.up * explosionForce * upliftWearoff;
    20.         body.AddForce(upliftForce);
    21.     }
    22. }
    23.  
    24.  
     
    pedrotepedinossauro and Mirodil like this.
  18. chodimirko94

    chodimirko94

    Joined:
    Oct 29, 2016
    Posts:
    1