Every solo dev I know has a version of this story: you open Unity, create a new project, and before you've written a single line of gameplay logic, you're already rebuilding player movement, a save system, a UI shell, and half a dozen other things you've built before. Not because those problems are hard anymore — because starting from zero is just the default habit nobody questions.
I questioned it eventually, mostly out of exhaustion, and it changed how I approach every new project since. This post is about what actually happens when you stop treating "built entirely from scratch" as the only legitimate way to start a game.
The pattern I kept repeating
I write mostly small mobile and casual games — puzzle mechanics, sorting games, the occasional runner. If you've worked in this space you already know these genres share a lot of structural DNA. A match-3 grid and a sort-puzzle state machine aren't the same game, but they rhyme hard: a 2D array of cell states, an input layer that translates touches into moves, a match/validity checker, a scoring system, a level-progression loader.
I had written some version of all of this at least four or five times across different abandoned and shipped projects before it occurred to me that I wasn't really learning anything new each time I did it. I was just paying a tax — the same debugging sessions for the same edge cases, the same UI wiring, the same "wait, why is this null on the first frame" bugs I'd already hit and fixed in a previous project's git history somewhere.
What changed
The shift was simple in concept and harder in practice: start from a working, already-tested implementation of the genre's core systems, and spend my actual hours on what makes this specific game different — mechanics twists, pacing, art direction, monetization structure — instead of re-deriving grid logic for the fifth time.
In practice this meant browsing for a genre-matched starting point instead of defaulting to a blank scene. I've pulled from libraries like the Unity game source code and template collection at Unity Source Code more than once when I needed a structurally sound base for a genre I already understood conceptually but didn't want to re-implement from zero for the umpteenth time.
To be clear about what this did and didn't do for me: it didn't make me a better engineer. It didn't teach me anything new about C# or Unity's component model. What it did was free up time that used to go toward repetition, and redirect it toward the parts of a project that were still genuinely new work.
Reading before touching
The single biggest mistake I made the first few times I tried this workflow was jumping straight into modifying a template without actually understanding it first. That's a recipe for exactly the kind of subtle, hard-to-trace bug that eats an entire evening.
My process now, before changing anything:
1. Trace the full lifecycle of a single level load,
start to finish, through the actual code.
2. Identify every singleton / manager class and what
owns state vs. what just reads it.
3. Find where Update() is doing per-frame work vs.
where things are event-driven.
4. Note anything that looks fragile or over-coupled
before I add a single new feature.
That fourth step matters more than it sounds like it should. Templates vary wildly in quality, and some of them have exactly the kind of fragile coupling that looks fine until you add one new feature and three unrelated systems break. Better to find that during a read-through than during a 2am debugging session three weeks before a planned release.
Where the actual performance risk lives
This is the part I think gets underrated the most, and it's worth its own section: performance-testing a codebase you didn't write requires different instincts than performance-testing your own code. You don't have the intuition for where the expensive operations are hiding, because you weren't the one who put them there.
A few specific things I now check on every inherited codebase before I trust it:
-
Per-frame allocations inside
Update(). This is the classic one — string concatenation, LINQ calls, ornewallocations happening every frame, invisible in the editor on a fast dev machine, brutal on a three-year-old mid-range Android device via GC pressure and frame stutter. - Coroutines that never get stopped. Templates built quickly sometimes leave coroutines running past the point they're needed, especially across scene transitions. This shows up as slow performance degradation over a play session rather than an obvious spike, which makes it easy to miss in a quick playtest.
- Physics or collision checks running on objects that don't need them. Grid-based puzzle games in particular sometimes inherit physics-based collision detection from an earlier prototype phase, when a straightforward array-index check would be both cheaper and more predictable.
- UI canvas rebuilds triggered more often than necessary. A surprisingly common source of frame hitches in mobile UI-heavy games, and one that's easy to introduce accidentally when you're wiring new UI elements into an existing canvas structure without checking how layout rebuilding is triggered.
I went deep on this exact topic — the specific silent performance issues that showed up after reskinning a template I trusted a little too quickly — in a longer writeup here: Reskinned a Unity Template — Here's Where the Silent Performance Bugs Hide. If you're about to ship something built on top of someone else's code, that post walks through the actual profiling steps and specific bugs I ran into, in more technical detail than I want to repeat fully here.
The architectural trap: two patterns fighting each other
One failure mode worth calling out explicitly, because it's easy to fall into without noticing: grafting a new feature onto an inherited codebase using a different architectural pattern than the one the template already uses. If the base project is built around a straightforward singleton GameManager, and you add a new feature using a fully event-driven architecture because that's what you're used to, you now have two competing mental models living in the same project.
This isn't just a style complaint — it creates real bugs. State can update through one path and not be reflected through the other, timing becomes harder to reason about, and anyone (including future you) reading the codebase has to context-switch between two different ways of thinking about how data flows through the game. Pick the existing pattern and extend it, or commit to a real refactor if you have a strong reason to change it. Don't let both patterns coexist by accident.
When to stop trusting the template and refactor
A working foundation isn't a permanent architecture — it's a starting point. If your game's scope grows meaningfully past what the original template was built to handle, layering more and more workarounds on top of the original structure eventually costs more than just refactoring the core systems properly.
The signal I look for: if I catch myself writing a workaround specifically to avoid touching an existing system, more than once for related reasons, that's usually the point where a proper refactor is cheaper than continuing to route around the problem. Templates save you the starting work. They were never meant to replace the thinking that goes into evolving a project past its original scope.
Is it still "your" game?
I'll address this directly since it's the question I see come up most in comments whenever this topic gets discussed: does building on top of someone else's source code make the final product less legitimately yours?
I don't think so anymore, and I used to think it did. The systems a template provides are almost never what a player actually experiences as "the game." Pacing, difficulty curve, art direction, the specific hook that makes someone want one more round — none of that comes from the boilerplate. It comes from the decisions layered on top of it. Two developers starting from the exact same template can ship completely different games, because the template was never the interesting part.
What actually matters is whether you understand what you're shipping well enough to debug it, extend it, and take responsibility for its behavior in production. That bar is clearable whether you wrote every line yourself or built carefully on top of an inherited foundation. One path isn't inherently more rigorous than the other — it's just slower, and slow doesn't automatically mean better.
Wrapping up
Starting from a tested Unity codebase instead of an empty scene changed where my hours go, not how seriously I take the engineering. I still profile everything. I still read code before I trust it. I still refactor when scope outgrows the original foundation. What I stopped doing is treating repetition as a badge of honor. If you've already built a category of system enough times to understand it deeply, there's no real lesson left in doing it again from zero — just time you could be spending on the parts of the project that are actually new.
If you're on the fence about trying this workflow on your next project: pick a template close to your target genre, read it fully before modifying anything, profile early instead of assuming it's clean, and be honest with yourself about when a workaround has become a sign that a real refactor is overdue. The time you save isn't free — it's time you're on the hook to reinvest in making the parts that matter actually good.
Top comments (0)