How to Stay Standing Up
If you want a game character or game object to stay standing upright, you can usually just set the game object’s rotation and forget it. However, if you are dealing with physics disturbances — such as being hit by flying soccer balls or running into a wall — then you’ll no longer be at the desired rotation or angle.
Physics disturbances can change the rotation of your game object depending on the location of the collision and the magnitude and direction of the external force. To return to the desired rotation, you can use a torsional spring simulation.
Math Background
A torsional spring simulation uses the following mathematical expression:
T = q * r * a1
Where T is the torque, q is the spring stiffness constant, r is the distance from the desired rotation in degrees, and a1 is the axis of rotation.
The above expression is sufficient, but you might find that this spring simulation is not as stable as you’d like, so we add a damper to this spring simulation. Adding a damper makes the torsional spring simulation more stable, more accurate, and you can set a desired angular velocity, so that the simulation never goes too slow or too fast. The following expression adds the damper:
T = q * r * a1 + p * w * a2
Where p is the spring damping constant, w is the difference between the current angular velocity and the desired angular velocity, and a2 is the axis of rotation for the angular velocity. Note that a1 and a2 are not necessarily the same axis of rotation vector.
Code Implementation
The following function computes the required torque to apply to the game object so that it stays standing up.
Vector3 getTorsionalSpringTorque (
Vector3 axisOfRotation,
Vector3 axisOfAngularVelocity) {
float r_ij = desRot — currRot;
float w_ij = desAngVel — currAngVel;
Vector3 springTorque =
Q * r_ij * axisOfRotation
+ P * w_ij * axisOfAngularVelocity;
return springTorque;
}
Note that the desired angular velocity is just like the two constants, they have to be tweaked and tuned until you find a value that works for you.
Helper Function
Also, you might run into the issue of how to find the correct axis of rotation. The axis of rotation will depend on the direction the game object was hit in 3D space, and thus which direction it rotated into. It could be hit from the front, which means that it will be knocked back, and the axis of rotation is either pointing to the left or right of the game object. On the other hand, the game object might be hit from the right, which means it will get knocked to the left, and the axis of rotation is either pointing in front of or behind the game object.
Here is some code to find the correct axis of rotation.
void getAxisOfRotation(out axisOfRot, out float r_ij) {
r_ij = arccos(dotProduct(Vector3.up, gameObject.upVector) );
axisOfRot = crossProduct(Vector3.up, gameObject.upVector);
}
Note that this function has two return values, so we make them return through the “out” parameters. The out parameters could also be referred to as references/pointers.
That’s it! If anything about Torsional Springs didn’t make sense, please review my Overview of Torsional Springs.
If you enjoyed this article, please ❤ to help others find it!