Pighaus Games Docs

These docs describe 1.1, the version on Fab. 1.3 is in testing: read its docs, or what changes when you upgrade.

Shakes

A shake is a data asset. Tune how it feels once, then anything in your game can play it by name.

A shake is a data asset. You tune what it feels like once, save it as something like SHK_Explosion or SHK_Gunshot_Heavy, and anything in your game can play it, including code that has never heard of the camera.

Shakes go through the same final stage as the rest of the camera: added to the bob and sway, scaled by the player's comfort settings, and kept from piling up into more than you authored.

Two kinds#

One shotLooping
Feels likea knock that rings outa steady rumble
Endsby itselfwhen you stop it
Good forimpacts, gunfire, landingsengines, wind, a charge building up
While it playsnothing to doset its intensity from 0 to 1

Playing one#

CallWhat it does
Play Shakeplays it and gives you a handle. Pass a direction for recoil or a hit from one side
Stop Shakefades a looping shake out. One-shots end on their own
Set Shake Intensityturns a looping shake up or down, 0 to 1
Play World Shakeplays one at a place in the world, weaker the further away you are. See spatial shakes
Play Engine Shakeplays one of Unreal's own camera shakes, so shakes from other packs still work

Tuning one#

Movement and rotation are the peak amounts per axis: centimetres forward, right and up, and degrees of pitch, yaw and roll. The balance between them matters more than the size of either.

Random Variation knocks a little off the strength each time it plays. Twenty shots from the same weapon at zero variation feel like a machine, which is right for a machine and wrong for most things.

Directional shakes push along the direction you pass in, instead of scattering randomly. Use it for recoil and for damage that came from somewhere. The direction is read relative to the character, so a hit from their left pushes from their left, whichever way the camera is facing.

Go deeperEnvelopes, for one-shots

A one-shot's spring decides how it wobbles; the envelope decides how strong it is while it does. Without one, the only shape you get is the spring ringing down, so a sharp crack with a long tail means making the whole thing sluggish. Tick Use Envelope, draw a curve, and it's stretched across Envelope Duration and multiplied in. The shake then ends when the envelope does.

Leave it off and nothing changes. Every setting on a shake defaults to how shakes behaved before it existed, so older assets need no attention.

Go deeperDifferent speeds per axis, for loopers

Noise Frequency is one speed for all three axes, which reads as a single texture. Axis Frequency Scale multiplies it per axis, so a heavy engine can heave slowly underneath a fast sideways buzz. It multiplies rather than replaces, so Noise Frequency stays the one dial that makes the whole shake faster.

Go deeperPlaying shakes without depending on the camera

Gameplay code shouldn't need to know the camera exists. A movement component that names a shake asset type drags the whole camera module in behind it, and the camera stops being optional.

So there's an interface, IBlendableFeedbackSink, with eight verbs: shake, rumble, jump charge, jump release, clear landing impact, burst, FOV punch and action charge. The effects component implements it. Anything that wants feedback calls the interface on the actor, and if nothing implements it, the call quietly does nothing. The shake is passed as a plain UObject for the same reason.

Each verb also has an ordinary Blueprint function on the effects component, for when you already have the component:

VerbDirect call
ShakePlay Shake, or Play World Shake for one with an epicentre
RumblePlay Micro Shake
Jump charge / releaseSet Jump Charge, Release Jump
Clear landing impactClear Landing Impact
BurstPlay Burst
FOV punchPlay FOV Punch
Action chargeSet Action Charge

To connect a plugin that has its own feedback interface, write a small adapter in your project: an actor component that implements their interface, finds the effects component at BeginPlay, and forwards each verb to the matching call. Your project is the one place that knows about both plugins, so the join belongs there.

More on shakes#

  • Spatial shakes: an explosion across the level isn't the same as one at your feet.
  • Mixing: what happens when several play at once.
  • Ambient shakes: the looping kind that belong to a shot and blend with it.