Exercise 4 — Juice It

GAME 1303-001 · Unity 6.x · Week 6 — Tuesday, September 29
In class, 10:30 – 11:45 · 2 points · Submit by end of class


The skill

Take the mechanic you built in Ex 2. Change none of its values. Make it feel ten times better.

Everything you add today is feedback — the game telling the player what just happened. Feedback is not decoration. A player who cannot tell whether their input registered will assume your game is broken, and they will be right to.

The trade secret is that game feel is almost entirely feedback, not physics. Two games with identical movement values can feel like a wet sponge and a rifle bolt. The difference is what happens in the 200 milliseconds around the input.

By the end of the block you will have: the same action from Ex 2, rebuilt with five layers of feedback, and a before/after recording that proves it.


What you need


Part 1 — Record the "before" (5 min)

1. Capture your baseline

Record 10 seconds of your Ex 2 verb, unchanged. Do this first. In forty minutes you will have lost all perspective on what it used to feel like, and this clip is half your submission.

Save as Docs/Ex04_before.mp4.

✅ Checkpoint 1 — a "before" clip exists, before you change anything.


Part 2 — The five layers (45 min)

Add them in this order, testing after each one. The order matters: it goes from most to least important, so if you run out of time you will have added the layers that count.

2. Layer 1 — Anticipation and follow-through (the most important, and the one everyone skips)

Nothing in nature moves instantly from rest to full speed. Add a wind-up before the action and a settle after it.

Three frames of squash and stretch will do more for your game than any particle effect.

3. Layer 2 — Sound

Add the SoundPlayer helper to an empty GameObject named Audio.

Fill the Sounds list with entries named exactly: jump, dash, impact, grab — whichever your verb uses. The helper scripts already call those names, so the moment you fill them in, your existing code starts making noise with no wiring.

Set pitchVariance to 0.08. Then set it to 0 and press the action ten times in a row. That fatigue you just felt is what your players would have felt for an hour.

4. Layer 3 — Particles

GameObject → Effects → Particle System. Save it as a prefab in Assets/Prefabs/.

Settings that matter for a short burst:

Spawn it at the moment of the action. If your verb uses Shooter, drop it in impactEffect; otherwise Instantiate it from your action, or trigger it from a UnityEvent.

5. Layer 4 — Screen shake

Add ScreenShake to your Main Camera.

PlayerMove2D and the verb helpers already call ScreenShake.Shake(). Set globalScale to 1 and play.

Now the important part: it is almost certainly too strong. Turn globalScale down until you can barely tell it's there, then leave it there. Good shake is felt, not seen. If a viewer would describe your game as "shaky", you have overdone it by roughly a factor of five.

6. Layer 5 — Hit-stop

The single most effective trick in action games: freeze the entire game for 2–4 frames at the moment of impact.

Add this to any script, and call HitStop(0.05f) at your impact moment:

public void HitStop(float duration)
{
    StartCoroutine(HitStopRoutine(duration));
}

System.Collections.IEnumerator HitStopRoutine(float duration)
{
    Time.timeScale = 0f;
    yield return new WaitForSecondsRealtime(duration);   // Realtime — timeScale is 0
    Time.timeScale = 1f;
}

WaitForSecondsRealtime matters. WaitForSeconds at timeScale = 0 waits forever, and your game locks up.

Try 0.03, 0.08, and 0.2. At 0.2 it feels broken. Somewhere around 0.05 it feels like impact.

✅ Checkpoint 2 — all five layers present and the action feels different.


Part 3 — Subtract (15 min)

7. Remove one layer at a time

This is the graded part. Turn each layer off, one at a time, and play. Ask: did the game get worse?

You will find that at least one layer is contributing nothing, and that one layer is doing most of the work. Almost always the heavy lifter is anticipation or sound, and almost always the passenger is particles.

Cut anything that isn't earning its place. More feedback is not better feedback — a game where everything shakes, flashes, and pops is a game where the player cannot tell what matters.

8. Record the "after" and write it up

Record the same 10 seconds. Save as Docs/Ex04_after.mp4.

Docs/Ex04_notes.txt:

Verb: Dash

Layers added:
  1. Anticipation   squash 1.15/0.85 for 0.05s before, stretch during
  2. Sound          "dash" whoosh, pitchVariance 0.08
  3. Particles      8-particle cone burst at the start point
  4. Shake          globalScale 0.35 (started at 1.0, way too much)
  5. Hit-stop       0.045s on landing a dash through a hazard

Which layer did the most:  hit-stop. Without it the dash reads as a
slide; with it, it reads as a punch through something.

What I cut and why:  particles. With sound and hit-stop already
selling the impact, the burst just added visual noise that made it
harder to see where I landed. Cutting it made the dash MORE readable.

No movement values changed from Ex 2.

The "what I cut and why" line is the point of the exercise. An exercise that adds five layers and keeps all five usually hasn't examined any of them.

✅ Checkpoint 3 — at least one layer cut deliberately, with a stated reason.


Part 4 — Build and submit (10 min)

9. Build

Into MyGameName/PC_Builds/Ex04/.

10. Submit

Zip as lastname_ex04.zip: the build, Ex04_before.mp4, Ex04_after.mp4, Docs/Ex04_notes.txt.

Canvas → Assignments → Exercise 4.


Rubric — 2 points

Criterion Pt Met when
Implementation 1 Build runs · at least four feedback layers present and firing on the action · no console errors · movement values unchanged from Ex 2
Design decision 1 Before and after clips submitted · at least one layer deliberately cut · notes name which layer did the most work and why the cut one was removed

Troubleshooting

The game freezes permanently after hit-stop.
You used WaitForSeconds instead of WaitForSecondsRealtime. At timeScale = 0, scaled time never advances, so the coroutine never resumes.

Particles don't appear.
Check the Particle System's Sorting Layer and Order in Layer — in 2D they render behind sprites by default. Also confirm Looping is off and Play On Awake is on for a spawned prefab.

No sound.
Sound names in SoundPlayer are case-insensitive but must otherwise match exactly. Confirm the clip is assigned, masterVolume isn't 0, and there is an Audio Listener in the scene (it lives on the Main Camera by default).

Shake never stops / camera drifts.
ScreenShake stores the camera's starting local position on Awake. If you move the camera by script, it will fight. Parent the camera to a rig object and move the rig instead.

Squash and stretch fights my sprite flipping.
If you flip by setting localScale.x negative, animating scale will undo the flip. Flip with SpriteRenderer.flipX instead.


If you finish early


Before next week

Ex 5 — Space & Pace: you build a real level with a gate, a key, and a checkpoint. It feeds the Level Map milestone in Week 8, so what you make next week is the beginning of what you submit the week after.