Skip to main content

7 posts tagged with "Architecture"

Game architecture and design patterns

View All Tags

Cross-Scene Events: The Persistence Problem Nobody Talks About

TinyGiants
GES Creator & Unity Games & Tools Developer

Your AudioManager plays background music. It subscribes to OnLevelStart to change tracks when the player enters a new area. You put the AudioManager on a DontDestroyOnLoad object so it persists across scene loads. Everything works during development because you're always testing in the same scene.

Then someone loads Level 2 from Level 1 for the first time. The music stops changing. The AudioManager is still alive — DontDestroyOnLoad did its job — but the event subscription didn't survive the transition. Or worse: the OLD subscription is still there, pointing at the destroyed Level 1 version of the event raiser, and the next time something tries to invoke it you get a MissingReferenceException in the middle of gameplay.

This is the persistence problem, and every Unity project with more than one scene hits it eventually.

Event System Pitfalls: Memory Leaks, Data Pollution, and Recursive Traps That Ship in Production

TinyGiants
GES Creator & Unity Games & Tools Developer

You've been testing your game for 5 minutes at a time. It runs great. Then QA files a report: "Memory usage grows steadily over a 30-minute play session. Frame rate degrades from 60 to 40 after loading 6 scenes." You profile it. There are 847 listeners registered to an event that should have 12. Each scene load added new subscriptions but never removed the old ones. The objects were destroyed, but their delegate references live on, pinning dead MonoBehaviours in memory where the garbage collector can't touch them.

Or this one: "Health values are wrong on the second Play Mode session. First run works fine." You hit Play, test combat, stop. Hit Play again. The player starts with 73 HP instead of 100. ScriptableObject state from the last session bled through because nobody reset it.

Or the classic: the game hangs for 3 seconds, then Unity crashes. Event A's listener raised Event B. Event B's listener raised Event A. Stack overflow. Except sometimes it doesn't crash — it just hangs, eating CPU in an infinite loop that produces no visible error.

These aren't hypothetical. These are bugs I've seen ship in production games. And they all have the same root cause: event system patterns that look correct in isolation but fail at scale.

Parallel vs Sequential: The Two Execution Patterns Every Event System Needs (And Most Don't Have)

TinyGiants
GES Creator & Unity Games & Tools Developer

Player dies. Death sound and death particles should start at the same instant — no reason to wait for one before starting the other. But the screen fade absolutely MUST finish before the respawn point loads. And the respawn MUST finish before the player teleports. And the teleport MUST finish before the screen fades back in.

That's parallel AND sequential execution in the same flow, triggered by a single event. And here's the uncomfortable truth: most event systems in Unity give you exactly one pattern. Fire an event, all listeners respond, done. Whether those responses should happen simultaneously or in strict sequence? Your problem.

So you solve it. With coroutines. And callbacks. And booleans named _hasFadeFinished. And before you know it, you've built an ad-hoc state machine scattered across six files that nobody — including future-you — can follow.

200 Events and Counting: Why Event Organization Breaks Down and How to Fix It

TinyGiants
GES Creator & Unity Games & Tools Developer

You start a new Unity project. You create ten events. OnPlayerDeath, OnScoreChanged, OnLevelComplete. You name them sensibly, drop them in a folder, and move on. Life is good. You can hold the entire event structure in your head.

Fast forward six months. You've got 200 events. The Project window is a wall of ScriptableObject files. You need OnPlayerHealthDepleted — or was it OnPlayerHPLow? Or OnPlayerHealthZero? You scroll through the list, squinting at names that all start with OnPlayer. After three minutes you give up and create a new one because you're not even sure if the event you want already exists.

This is where every event-driven Unity project lands eventually. And it's not because the event pattern is wrong — it's because nobody built the tooling for managing events at scale. Unity gives you the Animation window, Shader Graph, Timeline, the Input System debugger. Events get... the Project window.

Zero Reflection, Zero GC: What 'High Performance' Actually Means for a Unity Event System

TinyGiants
GES Creator & Unity Games & Tools Developer

Every single event system plugin on the Unity Asset Store says "high performance" somewhere in its description. It's right there between "easy to use" and "fully documented." But here's the thing — 1ms and 0.001ms are both fast in human terms, yet one is a thousand times slower than the other. When a plugin says "high performance," what does that actually mean? Compared to what? Measured how?

I used to not care about this. Most of us don't. You wire up some events, the game runs fine on your dev machine, you ship it. But then I started working on a mobile project with hundreds of entities each listening to multiple events, and suddenly "high performance" wasn't a marketing checkbox anymore — it was the difference between 60 FPS and a slideshow.

This post is about what "high performance" should actually mean for an event system, why most implementations fall short, and how GES achieves near-zero overhead through Expression Tree compilation. With real numbers, not hand-waving.

Unity's Generic Serialization Wall: Type-Safe Events Without the Boilerplate Tax

TinyGiants
GES Creator & Unity Games & Tools Developer

You build GameEvent<T>. Clean, type-safe, elegant. You create a GameEvent<float> field for health updates and slap [SerializeField] on it. You switch to the Inspector. The field isn't there. It's just... gone. Unity is staring at you with a blank panel like you asked it to divide by zero.

It's Unity's oldest architectural headache. The serialization system doesn't understand generics. It never has. And every developer who's ever tried to build a type-safe, data-driven event system has walked face-first into this wall.

This isn't a minor inconvenience. It's the kind of limitation that poisons your entire architecture. You either give up type safety, drown in boilerplate, or accept that your beautiful generic design will never touch the Inspector. For years, the community answer has been "just write the concrete classes by hand." But here's the thing — if the boilerplate is 100% predictable, why is a human writing it?

Goodbye Invisible Spaghetti: Why Your Unity Event System Is Killing Your Project

TinyGiants
GES Creator & Unity Games & Tools Developer

You renamed a method. Just one method — OnPlayerDied became OnPlayerDefeated because your game designer asked you to soften the language. You hit Play. Nothing happens. No compile error. No warning. Ten scene objects that were wired up through the Inspector with UnityEvents just... stopped working. Silently. And you won't find out until QA reports it three days later, or worse, your players do.

If this sounds familiar, congratulations — you've met invisible spaghetti code. It's the kind of technical debt that doesn't show up in your IDE, doesn't trigger compiler warnings, and doesn't appear in any dependency graph. It just sits there, waiting to break at the worst possible moment.

This isn't a skill issue. It's an architectural one. And it's way more common than most Unity developers want to admit.