When I started working on EcoRun, I thought the biggest challenges would be performance tuning and polishing the gameplay feel.
I was wrong.
The real challenge showed up much earlier and much quicker. It was architecture.
Like most endless runners, EcoRun began with a single PlayerController. Input handling, movement logic, jumping, sliding, collisions, even early power-ups everything lived in one script.
And at first, it felt great.
I was moving fast. Features came together quickly. The game was playable, responsive and fun.
The problem didnât appear immediately. It showed up the moment I added my second power-up.
Nothing was technically broken, but something felt fragile. Small tweaks caused unexpected side effects. Fixing one issue introduced another.
Thatâs when I realized I wasnât building a scalable game. I was stacking logic.
The Moment I Knew the Architecture Wouldnât Scale
At that point, I asked myself a hard question:
If I had to support this game for months, would I feel confident touching this code?
The answer was no.
So instead of pushing forward with more features, I paused and rethought the foundation.
Breaking the Monolith: Separating Responsibilities
The first decision was simple in theory but powerful in practice: one system should do one thing.
I stopped treating PlayerController as the owner of everything and started splitting responsibilities into focused systems.
- Input Handler â Interprets player input only
- Movement Controller â Handles movement and physics
- State System â Tracks running, jumping, sliding states
- Ability / Power-Up System â Modifies behavior without owning movement
None of these systems directly depended on each otherâs implementation. They communicated through events and interfaces.
This single change reduced coupling dramatically and made the codebase much easier to reason about.
public interface IPlayerAbility
{
void Activate(PlayerContext context);
void Deactivate(PlayerContext context);
}
Code language: C# (cs)
Instead of letting power-ups directly modify movement variables, each ability implemented a shared interface.
The PlayerMovement system never knew which power-up was active. It only reacted to the current context.
Power-Ups: Where Architecture Gets Stress-Tested
Power-Ups: Where Architecture Gets Stress-Tested
The easiest solution is also the most dangerous one directly changing player variables. Speed boosts, jump boosts, gravity overrides.
It works⊠until effects start stacking, expiring incorrectly or leaking state.
In EcoRun, I treated power-ups as temporary behavior modifiers.
They didnât own movement logic. They didnât permanently alter state. They simply applied effects for a limited duration and then cleaned up after themselves.
public class SpeedBoostAbility : IPlayerAbility
{
public void Activate(PlayerContext context)
{
context.SpeedMultiplier *= 1.5f;
}
public void Deactivate(PlayerContext context)
{
context.SpeedMultiplier /= 1.5f;
}
}
Code language: C# (cs)
This approach eliminated a whole class of bugs related to stacking and cleanup. More importantly, it made adding new power-ups predictable instead of risky.
Designing with Mobile Constraints from Day One
EcoRun is a mobile game and that fact influenced every architectural decision.
I didnât want performance optimizations to be an afterthought. I wanted the architecture itself to support them.
- Object pooling for obstacles and collectibles
- Minimal Update() usage
- Event-driven logic instead of polling
- Controlled physics interactions
public GameObject GetFromPool()
{
var obj = poolQueue.Dequeue();
obj.SetActive(true);
poolQueue.Enqueue(obj);
return obj;
}
Code language: C# (cs)
Because systems were already separated, optimizing one part never risked breaking another. That separation made mobile optimization straightforward instead of stressful.
What EcoRun Taught Me
The biggest takeaway wasnât a specific pattern or trick.
It was confidence.
Once the architecture stabilized, I stopped being afraid of adding features. Refactors became localized. Bugs were easier to diagnose because ownership was clear.
- Architecture matters most in âsimpleâ games
- Early separation saves months later
- Power-ups should modify behavior, not own logic
- Mobile constraints should shape design early
Closing Thoughts
EcoRun reminded me that moving fast and building right arenât opposites.
Sometimes the fastest long-term decision is to pause, rethink the foundation and build something you trust yourself to change later.
That mindset, not any individual mechanic, is what made EcoRun scalable and production-ready.
