Applying torque to smoothly stop at a desired rotation - factoring Mass and a Max torque
Okay, I'm just going to plainly lay out what I am trying to do because I simply can't find the solution to this. Every attempt I have made has failed miserably in one way or another.
Situation:
2D environment
No gravity
No drag
Variable mass
Variable Max possible torque
I need to be able to set a target direction, and have the torque managed in such a way that the object will always try to reach that direction without overshooting (Unless its existing velocity simply can't be overcome with its maximum torque)
If its not obvious, the object is a 2D spaceship and I'm trying to make the movement as physically based as possible to allow things like asteroids to knock into a spin that might take a few full rotations to decelerate from.
<- This is the point where I wish I could post some code thats almost there, but this is so far beyond my math/physics skill that I'm left with just asking for help.
I have looked at and implemented dozens of options I have seen across several forums/ask sites. Spent hours trying to modify them. None of them giving the results I need.
Edit: Just found https://youtu.be/ty9xm7U1ULA?t=42 which shows EXACTLY what I'm looking to do (the control and physics peace at least. It looks like the bottom left control gives the ship a forward vector and its doing its best to face that direction even after getting hit by something heavy)
If you have the time, please post the code as an answer, just in case the YouTube video goes down.
Ah, I should have been more clear. That youtube link is an example of the end result I'm going for, not an implementation.
Answer by lgarczyn · Dec 18, 2019 at 03:09 PM
There are a lot of ways to do this.
The easiest way to do this is to use Mathf.SmoothdampAngle
. Basically it has a target value, a current value, and a current velocity. It will automatically update the current angular velocity, and return the new position. It will never overshoot, and will always reach the target in a finite time.
So take the current angular velocity from the rigidbody, and input it with the current angle, target angle, some value for the time to change the controllability of the object, the max velocity and Time.fixedDeltaTime.
Then take the updated angular velocity, and apply it to the rigidbody. That's all. Every frame the rigidbody will apply the velocity, update the position, update the velocity because of drag. SmoothDampAngle will then recalculate a new velocity.
Because this function is not really made for this though, you might want to also set the new angle yourself on the FixedUpdate and/or remove the angular drag.
If you find the rotation too choppy, there are other possible tweaks. One of them is to update the position in both Update and FixedUpdate, but it requires calculating your own deltaTimes. You can do this because SmoothDamp is not sensitive to varying deltatimes.
You can also move to a kinematic rigidbody, and simply increment or decrement your own angular velocity on collisions, the use MoveRotation for perfect interpolation.