← Back to devlog
Engineering · July 2026

The Seesaw from Hell

I’ve been using Unity for a long time. I’m still losing the same argument with myself.

On one side: I want everything. Every knob, every tuning value, every bit of design-facing data authorable in the inspector. On the other: the inspector is a deadly, smelly swamp. Serialized data is scattered across prefabs and assets, no matter how much you mitigate it with flyweights and architecture. It becomes impossible to reason about three months later, causing more problems than it solves. I’ll live in one camp for a month, get burned, and drag all my tech debt to the other side of the fence. Then I get burned there and haul it back. Nobody wins. The seesaw never stops.

A new weight on the seesaw

Something changed recently that made this worse, and it’s agents.

Agents are terrible at reasoning about serialized logic. They come at your project from the file level. They’re reverse-looking-up GUIDs, hunting for objects scattered across the project, trying to piece together what’s wired to what. They have no idea what’s going on until they either spend forever building that context themselves or I stop and explain the whole setup to them. And with a codebase that’s constantly refactoring underneath them, it’s not even worth documenting as a long-term source of truth. The doc is stale by next week.

Code, they get. Code is right there, linear, greppable, self-describing. A serialized reference on a prefab is a black box with a GUID painted on the side.

So the seesaw that used to be about my future sanity now has a second rider. The stuff I bury in the inspector is the stuff my agents go blind on.

”Games are just rules and data”

I used to hold a naive opinion. Games are just rules plus data. The firm division of those two halves is what makes a well-architected game. Rules in code, data in assets, clean line down the middle.

I still think that CAN be true. You just have to spend a genuinely large amount of time deciding what data is worth exposing vs embedding.

How much damage a bomb does? Sure. Author it. How much radius it has when it explodes? Why not, that’s a feel thing. The number of units of radius the bomb tries to resolve its position to when it’s thrown into a space it isn’t allowed to settle on? Ehhhh.

That last one is a real value in my game right now. And I promise you nobody is ever going to open the inspector to tune it by feel.

”So just default it”

The obvious answer: throw it on there with a sensible default, and if you never need to change it, never change it. And you might be right.

It gets fuzzier the more complex the data is. A single float with a default is harmless. The problem is that “authorable data” doesn’t stay a float. It grows.

The nightmare tier

My biggest nightmares are things like UnityEvents. Serialized logic. They’re like magic. The ultimate answer to “Ugh. I have to write a script for this?” Actual behavior, wired up in a prefab, that you’d never know was there unless you remembered to go look.

People who know will pour one out for this. Your button fires twice. You dig through the code, you can’t find the second call, you’re losing your mind. Then you open the prefab and there it is: the callback is hooked up in code AND parked on the button’s serialized event list. The logic was in two places and only one of them was obvious during a bug hunt.

Now scale that up. State machines. Behaviour trees. These are whole layers of abstraction and tooling, built into the editor for humans to author in, and every one runs on serialized data that gets more and more complex the more you lean on it. The graph looks great in the window. It’s a carnival of madness on disk.

I’ve got a whole separate rant about one corner of this, ScriptableObjects getting asked to be a runtime switchboard. Same disease, different organ.

The one real payoff for all of it? Designers can do things without an engineer in their pocket. That’s genuinely valuable. Great.

The other side is also a hell

I have to be fair here, because the other camp isn’t paradise either.

Hardcode everything and you get a different nightmare. Magic numbers buried in scripts. A recompile every time you want to nudge a value. No tuning in play mode, no feel iteration, no handing a knob to someone who isn’t going to open Rider. I’ve built that project too. It’s rigid and miserable in its own way, and “just put it in code” is exactly the advice that lands you there.

Both extremes are bad. That’s the actual shape of the problem.

There is no t-shirt that fits everyone

So which camp is right?

Neither. That’s the part I finally believe after years on this seesaw. This isn’t a problem you get to generalize for. There’s no rule you write down once and apply forever. There’s no t-shirt that fits everyone.

The bomb damage wants to be authored. The position-resolution constant wants to be a named constant in code. The button behavior wants to live where I (and my agents) can see it. The enemy stat block wants to be a flyweight asset a designer tunes. Every one of those is a separate call, made on the specifics of that one piece of data: who tunes it, how often, whether a human needs to feel it, whether an agent needs to reason about it.

The discipline is making that call, honestly, case by case, every time. Picking a side was always the wrong move. The seesaw isn’t a problem to solve. It’s the job.

Ask me next month and I’ll probably tell you I’ve been dragging tech debt in one direction again. That’s fine. The insanity is part of the process.