Master Game Feel

A Step-by-Step Guide to Creating Squash & Stretch Components in Unreal Engine 5

📚 19 Step Tutorial
⏱️ 15 min read
🎮 Unreal Engine 5
💎 Professional Technique

Learn the exact component-based workflow used in professional game development to create satisfying, responsive interactions that players love. This technique transforms static objects into living, breathing game elements.

Squash and Stretch Example in Unreal Engine 5

Why Squash & Stretch?

Before diving into the implementation, let's understand why this principle is fundamental to game feel:

🎯 Instant Feedback

Players immediately understand object interactions through visual deformation

✨ Professional Polish

Transforms basic mechanics into satisfying experiences without additional assets

🔧 Component-Based

Reusable system that works across all your game objects

⚡ Lightweight

Minimal cost with maximum visual impact using just scale transforms

The Squash & Stretch Animation Cycle

Setup & Initialization

1

Create Component Class

We'll start by creating a reusable Actor Component that can be attached to any actor in your game. Navigate to your Content Browser and create a new Actor Component Blueprint named BPC_SquashStretch.

Creating an Actor Component in UE5
2

Set Class Defaults

Add these essential variables to your component. These will track our animation state and store the original scale:

Timer (Float): Default value = 0
bIsAnimating (Boolean): Default value = false
OriginalScale (Vector3): Set via Get Actor Scale 3D → Get Owner
Why store OriginalScale? We need to preserve the actor's default size so we can always return to it after animating. This allows the component to work with actors of any initial scale.
Component Variables Setup
3

Create Core Function

Add a new function named AnimateScale. This will be our main animation driver, called every tick to update the scale.

Creating the AnimateScale Function

🔓 Unlock Full Tutorial

Get instant access to all 19 steps with detailed screenshots and mathematical explanations

16 more steps Full source code Math explained

Animation Logic

4

Connect to Event Tick

Call AnimateScale from Event Tick. The boolean check we'll add prevents expensive operations when not animating, keeping performance optimal.

Connecting to Event Tick
5

Add Animation Gate

From AnimateScale, add a Branch node with bIsAnimating as the condition. This ensures we only process animation logic when needed.

Branch Condition: bIsAnimating
// False path → Return Node (exit early)
// True path → Continue animation processing
Animation Gate Logic

Squash Phase Implementation

6

Update Timer

Increment our timer by the frame's delta time to track animation progress:

Set Timer = Current Timer + Get World Delta Seconds
Delta Time Accumulation: The timer accumulates time since animation started. This frame-rate independent approach ensures consistent animation speed regardless of FPS.
Timer Update Logic
7

Configure Target Scale

Create a SquashScale variable (Vector3) with values like (1.3, 1.3, 0.7). This defines how much the object squashes - wider in X/Y, compressed in Z.

SquashScale: (1.3, 1.3, 0.7)
TargetScale = OriginalScale * SquashScale
Target Scale Configuration
8

Check Animation Phase

Determine if we're in the squash phase (first half) or stretch phase (second half):

Branch: Timer <= AnimationDuration / 2
// AnimationDuration (Float): Default = 0.2 seconds
// True → Squash phase (first 0.1s)
// False → Stretch phase (second 0.1s)
Why divide by 2? We split the animation into two equal parts. If total duration is 0.2 seconds, the first 0.1 seconds squashes the object, the second 0.1 seconds returns it to normal. This creates a smooth, natural bounce effect.
Animation Phase Check

Mathematical Precision

9

Calculate Alpha

Create a normalized alpha value (0 to 1) representing our progress through the squash phase:

Alpha = Clamp((Timer * 2 / AnimationDuration), 0, 1)
Why multiply by 2? Since we're only using half the duration for this phase (0 to 0.1 seconds), we need to double the speed to make Alpha go from 0 to 1 in that half-time. Without this multiplication, Alpha would only reach 0.5 when the squash phase ends.
Alpha Calculation
10

Interpolate Scale

Use linear interpolation to smoothly transition from original to squashed scale:

NewScale = Lerp(Vector):
    A = OriginalScale // Starting point
    B = TargetScale // Squashed shape
    Alpha = Alpha // Progress (0 to 1)
Scale Interpolation
11

Apply Scale

Apply the calculated scale to the owning actor:

Set Actor Scale 3D:
    Target = Get Owner
    New Scale = NewScale
Applying the Scale

Stretch Phase & Reset

12

Check Animation End

Determine if the animation has completed its full cycle:

Branch: Timer <= AnimationDuration
// True → Continue stretch animation (step 14)
// False → Reset animation (step 13)
Frame timing consideration: The timer might exceed our duration slightly due to variable frame timing. This check ensures we stop at the right moment and reset cleanly.
Animation End Check
13

Reset Function

Create a clean reset to end the animation:

Function ResetScale:
    Set Actor Scale 3D → OriginalScale
    Set Timer = 0
    Set bIsAnimating = false
Why reset to exact scale? Frame timing means we might not hit exactly 1.0 on our Alpha value. This explicit reset guarantees perfect return to the original size, preventing any drift over multiple animations.
Reset Function
14

Calculate Return Alpha

For the stretch phase, calculate alpha for the return journey:

Alpha = Clamp(((Timer * 2 / AnimationDuration) - 1), 0, 1)
Why subtract 1? In the second half, Timer goes from 0.1 to 0.2 seconds. Multiplying by 2 and dividing by duration gives us 1 to 2. By subtracting 1, we shift this back to the 0 to 1 range we need for the return interpolation.
Return Alpha Calculation
15

Interpolate Return

Lerp from the squashed scale back to the original scale:

NewScale = Lerp(Vector):
    A = TargetScale // Squashed (start of return)
    B = OriginalScale // Normal (destination)
    Alpha = Alpha // Return progress
Return Interpolation
16

Apply Return Scale

Apply the interpolated scale during the return phase:

Set Actor Scale 3D:
    Target = Get Owner
    New Scale = NewScale
Applying Return Scale
17

Create Trigger Function

Add a public function to trigger the animation:

Function TriggerSquashStretch:
    Set bIsAnimating = true
    Set Timer = 0
Public Interface: This is the function you'll call from other blueprints whenever you want the squash & stretch effect to play - on enemy hit, gun fire, jump landing, etc.
Trigger Function
18

Compile & Save

Compile your blueprint and save. Your component is now ready to use across your entire project!

19

Implementation Examples

Add the component to any actor and call TriggerSquashStretch to activate:

// Gun Firing
Squash: (1.3, 1.3, 0.7) // Wider and flatter
Duration: 0.15 seconds

// Enemy Hit Reaction
Squash: (0.7, 0.7, 1.3) // Thinner and taller
Duration: 0.25 seconds

// Pickup Collection
Squash: (1.5, 1.5, 0.5) // Extreme squash
Duration: 0.3 seconds
Adding Component to Actor
Using the Component

✅ Implementation Checklist

  • BPC_SquashStretch component created with all variables
  • AnimateScale function implemented with branching logic
  • Timer system and alpha calculations working
  • Squash and stretch phases properly interpolated
  • TriggerSquashStretch function ready to call
  • Component tested on game objects

Where to Apply This System

🔫 Weapons

Gun firing squash (1.3, 1.3, 0.7), reload animations, melee swings

👹 Enemies

Hit reactions (0.7, 0.7, 1.3), death squash, spawn animations

🎮 Player

Jump landing, dash moves, damage feedback

🖱️ UI Elements

Button presses, menu transitions, notification bounces

💎 Pickups

Collection squash, hover idle animation, spawn effects

🌍 Environment

Platform impacts, door slams, explosion debris

Ready to Level Up Your Game Development?

This tutorial is just the beginning. Master advanced Unreal Engine 5 techniques with our upcoming courses and free resources.

🎮 Full SHMUP Course

Coming Q1 2026 - Complete game development from concept to polish with advanced systems like this one

📺 YouTube Channel

Free tutorials on game dev fundamentals and UE5 techniques

Subscribe

💎 Patreon

Advanced tutorials, source files, and behind-the-scenes development content

Join