2026-09-02 · MITTENS THE KITTENS

Hearts, and two pads that finally drive two cats

Mittens has a visible health bar at last, the two gamepads finally drive two separate cats, and a ride that could trap you forever now lets go. Three of the day's bugs were the same shape — a write that succeeds and does nothing.

Project pageMore MITTENS THE KITTENS updates

A long night of fixing rather than building, and it was the right trade. Two of the day's finds had been silently breaking things for weeks.

Two gamepads drove one cat — because of our own debug tooling

The editor bridge creates a synthetic gamepad, and it enumerated at index 1 — between the two real controllers. Player two was bound to a phantom device nothing can press, and the second real pad was assigned to nobody.

The log said so all along: "P1 on Xbox Controller, P2 on Gamepad". That second entry was the ghost.

Native devices now sort ahead of synthetic ones, so a debug pad can never displace a pad a human is holding. The two cats resolve to completely disjoint control lists.

The warp boxes were rendering nothing at all

Reported as "one looks like a box, the other side looks like a shadow". The prefabs were on disk with null sprites — no arch, no collar, no tunnel. Not occluded. Invisible.

The asset build was clearing the wrong sprite cache, so the whole prefab pass could rebuild against stale art. A cache hit never logs, so nothing complained.

Health, hearts and a pickup

Mittens has three hit points and you could not see them. The health-changed event had been raised from five places to nobody for the life of the project.

Zelda-style hearts: hard keyline, pink ramp, specular in the upper-left lobe, and — the part most implementations get wrong — the empty heart keeps its outline, so you can count what is gone.

A pickup restores one. Three in the whole slice: one up an optional climb, one down in a sump, one on the mandatory route just before the boss door.

Nothing in this game had ever healed. The heal function had zero callers, and the food-bowl treat has claimed "restores health" in its own documentation while doing nothing but score.

Found while building it: the low-health pulse blanked the last heart for half of every cycle, and a dark last heart is pixel-identical to zero. The HUD was periodically telling you that you were already dead.

The ride that would not let go

Watch mode takes over by destroying the player's input component. The ride cached the original when you mounted and never re-resolved it.

Unity normally reports a destroyed object as null — but the reference was held as an interface, and that null-reporting behaviour is a compile-time overload chosen from the operand types. Through the interface the compiler picks plain reference comparison, so the check stayed true forever.

The dead object then answered every query with "stick centred, no buttons". No exception, no error. Mounted, that was an inescapable trap: the ride disables your controller, and the only way out is read from the same corpse.

Measured: stalls 11 → 2, embedded-body anomalies 16 → 2, and the ride now runs both directions.

New verbs

A claw scratch on the north face button. It reuses the existing claw damage path and the already-drawn slash art rather than forking a second one.

The dodge roll now ducks her body, so it can take gaps a standing cat cannot. Distance doubled to 5.6 units.

Doubling the roll alone would have broken the rule that stops it becoming a permanent dash, so the cooldown rose 0.45 → 0.9 to match. Chained rolls now average 4.4 units per second against a 5.5 walk — still slower than simply running, which is the property worth protecting.

The shape of the day

Three separate bugs were the same shape: a write that succeeds and does nothing.

Pausing during a hit-stop left its driver ticking on an unscaled clock behind the menu; when it finished it restored the timescale, and the game resumed running underneath the open pause screen.

Both cats stop announcing deaths globally — that is how nine-lives-each works — but nothing had picked up the presentation. No death sound, no drowning sound, no screen flash, for an entire two-player run. Three boss events were raised the same way, with nothing subscribed.

And the roll and double jump could not be tuned at all: every one of their fourteen fields was absent from the movement asset. They worked only because code defaults filled in behind them. Anyone opening that asset to tune the roll was editing a file the roll was not in.

Also fixed

Score came from three tables that disagreed — a paw token was worth 10 in one and 100 in another. Collapsed to one source of truth.

Co-op tore the swim input filter off both cats, in the stage that is entirely about water.

A hurled enemy could dismount you: its damage box stayed live in flight and overlapped by exactly one pixel, so it fired for some enemies and not others.