- Home /
How can I smooth damp the rigidbody2D rotation at the end?
I've a sprite in my scene. It has a rigidbody2d component with "Gravity Scale = 0". When I press the up and down keys the sprite rotates. At 45/-45 degrees it stops hard. How can I make a smooth damp at the end rotation? Does somebody has any idea?
public Transform myTransform;
public Rigidbody2D myRigidbody2D;
private float axisVertical = 0f;
public float speed;
void Update()
{
axisVertical = Input.GetAxisRaw("Vertical");
float rotationX = myTransform.localEulerAngles.x;
if (rotationX > 45)
{
myTransform.localEulerAngles = new Vector3(45, myTransform.localEulerAngles.y, myTransform.localEulerAngles.z);
}
else if (rotationX < -45)
{
myTransform.localEulerAngles = new Vector3(-45, myTransform.localEulerAngles.y, myTransform.localEulerAngles.z);
}
}
void FixedUpdate()
{
myRigidbody2D.AddTorque(-axisVertical * speed * Time.fixedDeltaTime);
}
Answer by xxmariofer · Jan 17, 2019 at 03:42 PM
Try out slerp i think will work for you:
https://docs.unity3d.com/ScriptReference/Quaternion.Slerp.html
not by itself, it won't. there's still going to be a hard stop. to smooth it out, you'll then have to run it through some nicely drawn curve.
also, it would require for him to rewrite all of his code
Lerp interpolates between 2 vectors so is not going to hard stop since it will be getting closer to the end point the interpolation will be lower, but of course if he wants the best solution would be to create a Curve and modify it in inspector for getting the velocitys over lifetime.
oh, you didn't specify where he should use it, so I assumed something I usually do, meaning lerp from -45 rotationX to +45, not lerping the torque force added.
Answer by sh_code · Jan 17, 2019 at 04:04 PM
what you want to do, is the closer you are to the limit of your angle, the slower you're rotating, meaning the less torque you're adding. so instead of
myRigidbody2D.AddTorque(-axisVertical * speed * Time.fixedDeltaTime);
you want to do something like
myRigidbody2D.AddTorque(-axisVertical * ((45 - Mathf.Abs(rotationX)) / 45) * speed * Time.fixedDeltaTime);
notice the new part: ((45 - Mathf.Abs(rotationX)) / 45)
this means that as your rotationX is approaching 45, the part saying "45 - abs(rotationX)" gets closer to zero. the division at the end, "/ 45" just "normalizes" the value to make it be between 1 and 0. so at rotation 0, the expression evaluates to 45 - 0 divided by 45, which is one, which is full-strength torque, and as the rotation approaches 45, the expression's value will approach 0, which, when you use it to multiply the rest of the values, will be decreasing them up to the point when at 45degree angle, you're adding a torque of 0, thus none.
this is the simplest way to do it for your current code, it's linear dampening.
the better way, which would allow you to tune the feel in more detail, would be to put one more indirection in there - instead of directly using the result of the expression, make an AnimationCurve from 0 to 1 (if you make it as a public variable, you can edit it visually in the inspector), and then plug the number into AnimationCurve.Eval, which will return the value in the curve at that position, enabling you to draw the dampening behavior in any way you want.
that would mean (besides making the animation curve) changing that line of code into:
//define this new variable and in Inspector, edit its curve going from 0 to 1 on x axis, and whatever the rotation intensity you want on the Y axis
public AnimationCurve rotationDampeningCurve;
myRigidbody2D.AddTorque(-axisVertical * rotationDampeningCurve.Eval((45 - Mathf.Abs(rotationX)) / 45) * speed * Time.fixedDeltaTime);
Codes are not working. The problem here is, when the sprite rotates to the end it is not rotating anymore when I press the up and down keys. It is stuck at the end.
oh, dang, yes. sorry. i should have realized that.
well then, we won't be able to avoid conditions...
assu$$anonymous$$g what you're trying to do is rotate left when input axis is moved upwards, and right when input axis is moved downwards:
if((axisVertical < 0 && rotationX > 0) || (axisVertical > 0 && rotationX < 0)){
myRigidbody2D.AddTorque(-axisVertical * ((45 - $$anonymous$$athf.Abs(rotationX)) / 45) * speed * Time.fixedDeltaTime);
}
else {
myRigidbody2D.AddTorque(-axisVertical * speed * Time.fixedDeltaTime);
}
notice the condition. basically what it says is "if we're closer to the rotation limit at the same side as we're trying to rotate towards, apply the dampening". and in any other case (meaning we're closer to the rotation limit which we are trying to rotate AWAY from), don't apply dampening.
NOTE: i got a bit confused about what your intention is. your current code seems to rotate to the left when up arrow is pressed, and to the right, when down arrow is pressed, which is, mathematically, opposite to the... natural thing.
because by default, rotation to the left are negative angles, and movement down==down arrow is negative numbers too. and then rotation to the right is positive angles, same as movement upwards is positive numbers.
if you left the controls like this, then the condition would make more sense on the first glance, it would be:
if((axisVertical < 0 && rotationX < 0) || (axisVertical > 0 && rotationX > 0))
...notice how both comparisons in a pair are in the same direction. that's saying "if we're trying to rotate in the same direction as we're already nearing the boundary of".
but it seems you wanted up arrow to rotate left, and down arrow to rotate right, which is why you use the "-axisVertical" in the AddTorque... which is why the condition for your solution (the topmost one in this post) seems weird, it's saying the same thing, but the comparison operators in the pairs are opposite, so it looks like it makes no sense, but it's the same thing, only your controls are reversed compared to what's mathematically natural, so the comparison needs to reflect that.
...i might have confused myself (and you) a bit, but one of those two conditions is going to work =D
please try out and let me know =D
Thank you for your help. Your code works, but it's still hard stop at 45/-45 degrees. I think, that the problem is the AddTorque(). It gives a lot angular velocity. I must rewrite the code.