Techniques to Calm Down Jittering Joints in Unity

Hi! This is the very first post in my blog in English.

I usually write articles only in Japanese, but this time I’ve decided to write the article in English as well, because I couldn’t find any relevant post even in English. I hope this helps people who suffer from similar problems.

This is the English translation of this blog post and the content is basically the same, but there’re maybe small differences (mainly because of my English skills lol).

Have you ever tried to make a chain or a rope in Unity, ended up getting rigid bodies violently moving around just like the image above? Well, I have too.

This post explains techniques to calm down jittering joints, digging into the systems of physics engines to reveal what truly make them jittery, and why the techniques are so effective.

Making an actual scene

I made this simple scene in Unity.

The gray cube is set to Kinematic, the yellow spheres and the red cube are set to Dynamic. And these are connected by Character Joints at the points they’re touching. Also, I set the masses of the yellow spheres to 1.0, and the mass of the red cube to 10.0.

When I drag the red cube a little after starting the scene…

The chain starts to flail around.

Why do they jitter in the first place

That’s because physics engines aren’t good enough.

・・・

To be fair, this kind of problem is generally difficult for physics engines[1], especially for those simulate stuff in real time. PhysX, which is used in Unity, does suffer from the same problem as well.

When you connect things with a chain, the chain is likely to have far havier objects on its ends than the chain itself. That is, you’re likely to connect things in the order of:

Heavier — Lighter — Lighter — … — Lighter — Heavier.

When you get used to physics engines you can tell that this ordering is one of the worst thing we can do to physics engines. Even the official Unity manual says that you should avoid these kinds of configurations.

Avoid large differences in the masses between Rigidbody components connected by Joints. It’s okay to have one Rigidbody with twice as much mass as another, but when one mass is ten times larger than the other, the simulation can become jittery.

Well, this description is not so much accurate, since we’re not going to have any unstable simulations unless very light rigid bodies are sandwitched by heavier ones. When a rigid body is connected to the background of a scene with a joint, the mass difference is infinity but the simulation would be totally stable.

I’m going to explain why light objects sandwitched by heavier ones can be a cause of unstable behavior. The following description contains some simplifications, but doesn’t miss the essence of the problem I believe.

Why large differences in masses cause instability

Imagine three objects 1, 2, and 3 are lined up, and two people A and B are connecting the objects 1 and 2, 2 and 3, respectively. What two people have to do is to keep the distance of the objects that each person is connecting. But keep in mind, that the object 2 is way lighter than the other objects.

[1]---A---[2]---B---[3]

Now, something appeared and pulled objects 1 and 3 horizontally with a large force.

[1]--------A--------[2]--------B--------[3]

As a result, they’ve been stretched. So, two people A and B now try to haul the objects closer so that they would restore their initial distances.

First, the person A computes how much they need to pull the objects 1 and 2 to restore the initial distance betwwen them, and pulls the objects accordingly. But remember that the object 1 is much heavier than the object 2 and barely moves.

Consequently, the object 2 moves to the left a lot, and the object 1 moves to the right slightly.

[1]---A---[2]----------------B--------[3]

They restored the initial distance anyway, and the person A now looks satisfied.

But what about the person B? The situation is even worse now since the object 2 is pulled to the left greatly.

Then the person B tries to haul two objects closer similarly, but indeed the object 3 is much heavier than the object 2 and barely moves again.

[1]---A-------------------[2]---B---[3]

The person B now looks satisfied too as they successfully restored the initial distance.

But not again! The person A has to pull the objects 1 and 3 once again.

In that way, they keep tugging the lighter object 2 from each other extermely.

[1]---A-------------------[2]---B---[3]
  [1]---A----[2]----------------B---[3]
  [1]---A---------------[2]---B---[3]
    [1]---A----[2]------------B---[3]
    [1]---A-----------[2]---B---[3]
      [1]---A----[2]--------B---[3]
      [1]---A-------[2]---B---[3]
        [1]---A----[2]----B---[3]
        [1]---A---[2]---B---[3]

They’ve finally got their initial distances and settled down.

But what if the three objects 1, 2, and 3 had the same masses in common? Since they’re equally heavy, each person would pull two objects the same distance. Therefore, the things would be like:

[1]--------A--------[2]--------B--------[3]
     [1]---A---[2]-------------B--------[3]
     [1]---A----------[2]---B---[3]
         [1]---A---[2]------B---[3]
         [1]---A----[2]---B---[3]
          [1]---A---[2]---B---[3].

They achieved the initial distances in fewer iterations.

Essentially, the exactly same thing happens in physics engines, being one of the cause of unintended behavior of joints.

Lowering the mass of the heavy object

The big difference in the masses seems like the reason why the chain jitters, so let’s try decreasing the mass of the red cube from 10.0 to 1.0.

It stopped jittering.

But it doesn’t look like hanging a heavy object anymore, since we changed the mass of the red cube to the same value of each yellow sphere has (not to the sum of those!).

Furthermore, when I drag the cube a bit stronger…

It started to jitter again! There seem to be other reasons than the mass ratio it jitters.

The nonlinearity of rotations

In fact, much of the reason joints jitter is not in large differences in masses, but in the rotational motions.

Large differences in masses can be a cause of stretchy joints. But when joints violently jitter like in this case, the true cause tends to be the rotational motions.

This is also closely related to how physics engines work.

Linear equations and solvers in physics engines

Things will be a bit more difficult from here. Rigid-body physics engines[2] like PhysX, Box2D, and Bullet Physics solve linear equations in order to compute how much forces (impluses actually) should be applied to each contact point or joint.

Technically they have to solve nonlinear equations for cone frictions and linear complementarity problems for normal contact forces, but these equations can be solved by a variant of the Gauss-Seidel method which is used to solve linear equations, so you can think of these equations essentially as linear equations here.

The translational motion of a rigid body is linear. When a rigid body located at \bm x translates by linear velocity \bm v, the position of the rigid body after time t can be exactly predicted as \bm x+t\bm v. So, solvers can predict the change in positions from linear velocities accurately.

However, the rotational motion of a rigid body is nonlinear. Let’s consider it in 2D for simplicity. The trajectory of a point at \bm r\ (\neq\bm 0) on a rigid body that rotates at the origin with angular velocity \omega will be a circle instead of a line.

Therefore we need the following nonlinear representation to predict the exact position of the point after time t:

\begin{pmatrix}
    \cos(t\omega) & -\sin(t\omega) \\
    \sin(t\omega) & \cos(t\omega)
\end{pmatrix} \bm r.

But it’s impossible to embed it in a linear equation decently. So let’s approximate it:

"The motion is actually rotational, but if you look at it for a very short period of time, it looks like almost moving linearly, so use it as the approximation of the original motion."

Well, it’s just a differential. The true orbit of the black point (the red arrow) is approximated by the linear one (the blue arrow). As you can see, it’s very accurate at first, but as the time goes on, the approximated orbit deviates greatly from the true one.

In practical physics engines, the positions of rigid bodies are usually updated at intervals of 1/60 second. So if rigid bodies rotate a lot within these intervals, the accuracy of the approximations of the rotational motions deteriorates, and the solver can no longer know the exact positions in the next time step.

Guess what happens then?

Joints start to jitter.

Increasing solver iterations doesn’t work

And what is worse, you can’t solve this problem by increasing the number of velocity iterations of a solver.

When a big mass ratio is the problem, the solver is basically just slow in solving equations, so increasing the number of iterations helps a lot. In this case however, the solver fails to put the situation into equations accurately in the first place, so increasing the number of iteration won’t help at all.

Let’s try it out.

Open Unity’s Project Settings and choose Physics tab, set Default Solver Iterations to 100. This is kind of an impractical and extreme configuration that enables the solver to handle absurdly large differences in masses that usually totally mess up the simulation.

Go back to the editor, start the scene, and then try dragging the cube.

For all the solver’s hard work, the joints start to jitter like it’s nothing. Ah, note that the mass ratio is 1 now because I set the red cube’s mass back to 1.0. I guess now you can tell how horrible rotational motions are.

P.S. Although increasing the number of iterations doesn’t work, decreasing the time step would greatly help since it improves the accuracy of the approximation of rotational motions. The drawbacks of this approach can be: we need extra treatment to match the motions between the game and the physics simulation, the amount of required computation increases in reverse proportion to the time step.

Column: Box2D is great

Among the physics engines I mentioned earlier, Box2D has exceptionally robust joints. This is because Box2D has a nonlinear solver that can take account of rotational motions in addition to normal solvers. If you’re interested, I reccomend you search for "Nonlinear Gauss-Seidel"[3].

There is also a feature in Unity that has similar effects, which is named "Joint Projection". However, this doesn’t really help calming down jittering joints; it just gives satisfactory visuals for ragdolls so that their limbs don’t get unnaturally elongated in a poor situation.

In Bullet Physics, Featherstone’s algorithm is implemented and using it will perfectly solve chain-shaped connections[4]. Although it has a strong advantage that chains doesn’t stretch at all, it ocationally shows some kind of instability due to the nature of direct methods, and it can’t handle any structures that include loops. Also I still don’t completely understand the algorithm since it’s very complicated! I hope I’ll someday understand and implement it.

How to settle down jittering joints

The main topic. Now that we know the problem lies with the rotational movements, let’s make the bodies hard to rotate. The key is moment of inertia[5].

Increase the moment of inertia

I believe everybody knows that a heavy object is hard to move. In other words, it means that it is difficult to change the translational velocity of an object that has a large mass. If we replaced "translational velocity" with "angular velocity", the counterpart of "mass" would be "moment of inertia". That is, the moment of inertia of an object defines how hard it is to rotate the object.

If you can use C#, let’s increase the moments of inertia of rigid bodies that consist the chain. It seems like you can access the parameter through RigidBody.inertiaTensor. Don’t make them too large or your simulation would look weird. You need to keep them just as small that joints still don’t start to jitter.

Just in case if people somehow don’t have access to C# scripts, I’ll introduce the way to increase a rigid body’s moment of inertia through Unity Editor.

Increase moment of inertia through Unity Editor

You can find the moment of inertia of a rigid body in Inspactor → Rigidbody → Info.

It’d be great if we could tweak the values there, but they’re grayed out and we can’t edit them. Sadly.

Apparently these values are computed based on Colliders attached to the rigid body, so the chances are that we can change them by doing something with Colliders.

The nature of moment of inertia

Here’s a sudden question: which one is heavier, a metal ball of mass 100 g, or a foam ball of mass 100 g?

Of course, they weigh the same. Then, what about their moments of inertia?

In fact, the foam ball has much larger moment of inertia. This is because the mass of the object is widely distributed. In other words, much part of the mass is distributed far away from the object’s center of gravity.

If you actually tried to twist the foam ball, you might not find it more difficult than you do the same thing for the metal ball. However, the principle of leverage works here, making you feel a lot easier to generate the same torque thanks to the large radius of the foam ball.

Craft Colliders

Given all these above, what should we do to make the moment of inertia larger that is computed from attached Colliders?

The answer is simple: make the Collider large.

I made a bold decision to make the radius of the Sphere Collider five times larger. Let’s see how the values changed.

Although the total mass is unchanged, the moment of inertia is now 25 times larger! Generally speaking, when you make an object r times larger keeping the total mass and the ratio of the density distribution, the object will get an r^2 times larger moment of inertia.

But this change makes the ball just actually larger, so we’re going to make the use of Layers so that we can separate an imaginary Collider that is used only for mass calculation from a Collider that is actually used for collision detections.

Open Project Settings and choose Tags and Layers, and add a dummy layer (I named it Ghost). Then open Physics tab and uncheck the whole column of the Layer in Layer Collision Matrix.

Now you can add a Collider to the Ghost layer to prevent it from functioning.

Note that if you checked the Is Trigger box, the Collider would be excluded even from the mass calculation so make sure you leave it unchecked.

Set the layer of the ball to Ghost and enlarge the attached Collider,

and add a child object in Default layer that only has a Collider that has the original size.

Now both of the Colliders will be used for the mass calculation, but the larger one will be excluded in collision detections.

Check the result

Let’s see how it works! Play the scene and drag the red cube.

It’s surprisingly stable as if it had always been so! Now it won’t jitter and backs to normal very soon even if you drag it so hard.

Changing the mass of the cube from 1.0 to 10.0

It became a bit springy, but the movement itself is stable. The springy effect is due to the large mass ratio, so you can reduce it by increasing the number of iterations of the solver.

Let’s chenge it from 6 to 20.

Now it hardly stretches. You can see that the solver is performing as it should be! The only thing stretched is the time consumed by the solver.

Column: add auxiliary constraints to make it even stiffer

In cases like this one, it is effective to add auxiliary constraints to make the joints hard to stretch.

For example, suppose that the initial distance between the root of the chain and the anchor point of the cube (= the other end of the chain) is l. If the chain doesn’t stretch at all, The distance between the two points wouldn’t be greater than l at any time. So, we directly connect the cube to the root of the chain by a joint that limits the maximum distance between the two points to l. By doing this, the load on the chain will be greatly reduced and the chain becomes almost non-stretchable[6].

Box2D has Rope Joint that is dedicated for this usage, but unfortunately Unity doesn’t seem to have Rope Joint or even Distance Joint, so it’s probably difficult to do the same thing. Maybe Spring Joint can play the role to some extent, but I don’t know.

By refining this notion of auxiliary constraints, we ultimately reach the multigrid method, but I would rather leave this story for the future.


Any questions or suggestions? Send them to my twitter account!


  1. More generally speaking, iterative methods suffer from the same problem. This is related to the condition number↩︎

  2. this includes OimoPhysics which I developed ↩︎

  3. OimoPhysics also has an option to run Nonlinear Gauss-Seidel solver. It’s a homage for Box2D. ↩︎

  4. or more generally, tree-shaped connections ↩︎

  5. Also called inertia tensor or moment of inertia tensor, since it’s a second-order tensor. We call it moment of inertia here. ↩︎

  6. this technique is used in the Works page on oimo.io ↩︎

このエントリーをはてなブックマークに追加