Programatic Squash and Stretch

Squash and Stretch are one of the fundamental concepts of animation. If you are like me, and don’t fancy animating a hundred variations of every animation, you can programmatically add this juicy effect. Here’s how.

The Shader

First we need a shader to actually display our squash and stretch. This is as simple as modifying an unlit shader to multiply the default vertex positions by a transformation matrix.

The code below is only the important bits, you still need the rest of the shader!

The Script

Now we need a script to set this matrix. For the actual setting, I’ll use material property blocks. First we need to declare and create this block.

Next we need to construct our stretch matrix. This part is largely up to you how you want to do it, but I’ll show you how I’ve done it:

First I’ll explain the variables:

  • acceleration: The current acceleration of the character. I actually smooth this out using exponential smoothing for a nicer effect.

  • velocity: The current velocity of the character. Again, I smooth this.

  • accScale: How much acceleration should stretch the character.

  • velScale: How much velocity should stretch the character.

  • maxStretch: maximum stretch scale

  • Offset: offset where the character is stretched from. I actually use a different offset when the character is in the air or grounded.

Lines 4-5 make sure that when the character hits the ground, the player squishes horizontally, despite the acceleration being vertical. Basically the Vector2.Dot will return negative if stretch and velocity are in opposite directions, i.e., we are decelerating.

Lines 13-25 are generating the matrices. Line 25 is worth explaining. We can only stretch directly along the x and y axis. We need to stretch along the axis of acceleration (or velocity or a combination). To do this, we rotate our character so that the velocity aligns with the x axis, stretch them along x and y, then rotate them back. this gives us

m = r_inverse * s * r

Similarly, we can only rotate around the origin, so we need to shift the character so that the origin is where we want to rotate around. After rotating, we need to shift back. All together this gives us

m = t_inverse * r_inverse * s * r * t

Finally, lines 27-29 set the matrix in the shader. And we are done!

Happy stretching!

Leave a comment

Your email address will not be published. Required fields are marked *