Live data from Hacker News

A Thought Experiment: Using the ECS Pattern Outside of Game Engines

adventures.michaelfbryan.com

21–30 of 75 posts

Re: A Thought Experiment: Using the ECS Pattern Outside of Game Engines

#21
In the Clojure world, this used to be a popular way to structure backend apps: https://github.com/stuartsierra/component

> Components provide some basic guidance for structuring a Clojure application, with boundaries between different parts of a system. Components offer some encapsulation, in the sense of grouping together related entities.

> Each component receives references only to the things it needs, avoiding unnecessary shared state. Instead of reaching through multiple levels of nested maps, a component can have everything it needs at most one map lookup away.

Re: A Thought Experiment: Using the ECS Pattern Outside of Game Engines

#22
post #19

Earlier quoted context omitted.

Not that different from MVC a couple decades ago, then! :D (just kidding) I love the history of ECS. Scott Bilas' goals with his work in Dugeon Siege, and before that, in Gabriel Knight 3 [1], was to have something close to what you're doing, in order to speed up development. He was storing game logic in text files, as opposite to having it hardcoded, to enable level designers and artists to iterate faster. I guess h…

Didn't know that origin story, thanks! FWIW, what I'm doing is storing all the runtime state in in-memory SQLite, instead of writing my own ECS. Components are rows in tables, entity IDs are used as foreign keys, game logic just does regular SQL SELECTs to query the game state, and then UPDATEs, INSERTs or DELETEs stuff as needed. I came up with this experiment when I was writing yet another implementation of ECS for…

That's super cool. I think that approach is quite scalable, too. Only games with very complex logic would require something faster than SQLite for game logic.

Unrelated, but I also guess that using SQLite for offline data could be a timesaver, since you can leverage web tech to make tooling for your artists and level designers.

Re: A Thought Experiment: Using the ECS Pattern Outside of Game Engines

#23
post #21

In the Clojure world, this used to be a popular way to structure backend apps: https://github.com/stuartsierra/component > Components provide some basic guidance for structuring a Clojure application, with boundaries between different parts of a system. Components offer some encapsulation, in the sense of grouping together related entities. > Each component receives references only to the things it needs, avoiding un…

Used to be? What replaced it? I used it in my last Clojure project, and I'm about to start expanding it further; should I replace it with something else?

Re: A Thought Experiment: Using the ECS Pattern Outside of Game Engines

#24
post #5

How is an Entity Component System different from Objects and Controls in something like Visual Basic for example?

Visual Basic controls are more like React components, I think.

ECS is, traditionally, just a way to dynamically add behaviour (components) into "blank slate" entities.

Instead of making a EvilMonster class in a game you just have it as a conceptual entity (normally it's just an integer, like a database id) associated with a bunch of components (normally just plain structs) and their parameters: Renderable, RigidBody, Collider, HasEnergy, HasTransform, AudioEmitter, etc.

You can stitch entities and components together using either code or some external data source. The "S" part of ECS is called the system, and it implements the behaviour defined by components.

The upsides of this IMO is that this is a fantastic way to structure your code. The data-oriented aspect is also great for enabling non-coders to assembly complex entities. And some other clever people (such as the sibling answer) found out this is also a great optimisation technique.

There are multiple implementations, of course, so people have different opinions.

Re: A Thought Experiment: Using the ECS Pattern Outside of Game Engines

#25
post #3

I find ECS a pretty intuitive concept, but it always ends up being a massive yak shave to me

What were your problems with it? Was it using a particular library or engine, or you did it yourself?

I'm curious because I started using ECS-like techniques exactly because traditional OOP in games felt a lot like yak shaving.

Re: A Thought Experiment: Using the ECS Pattern Outside of Game Engines

#27
post #3

I find ECS a pretty intuitive concept, but it always ends up being a massive yak shave to me

When performance matters I often find myself yak shaving existing code to basically turn it into structure-of-arrays format (like is required for ECS), if not converting to ECS entirely. The alternatives scale so poorly...

Re: A Thought Experiment: Using the ECS Pattern Outside of Game Engines

#28
post #14

Earlier quoted context omitted.

The critical differences are memory layout and explicit declaration of logical dependencies: this makes the code parallel by default.

This is just false unless you think the featured article isn't ECS. Rendering is an ordered operation that at the very least shouldn't be considered parallel by default. Simply putting it in an ECS pattern doesn't guarantee anything like that. Its probably better to say it might help you write tighter loops because (ideally) you have a small amount of code looping over a large array of data, instead of a sea of actor…

Rendering on modern hardware is fundamentally parallel by default, even if the commands you issue appear to be sequential. In practice multiple commands can be issued in parallel by a modern GPU and fragments are rasterized in parallel as well (divide and conquer), see https://youtu.be/Nc6R1hwXhL8?t=465 and note how it's chunking many triangles up into groups and rasterizing them in parallel (there's a predictable spatial order, but it's not rendering one tri at a time or one screen quadrant or a time). This is necessary to exploit the massive number of cores on these GPUs (thousands, in some cases).

Newer graphics APIs also allow you to build many command buffers at once (in parallel) and allow you to fill GPU vertex/index/texture buffers in parallel from multiple threads once you've mapped them into your address space.

GPU compute is also basically async and operates in parallel with rendering on modern GPUs. See https://www.extremetech.com/extreme/213519-asynchronous-shad...

Rendering is, in practice, parallel. You can enforce sequential ordering if you need it, but you often don't. (Z-buffer based rendering effectively makes parts of your scene parallelizable since the rendering is order-independent, and as demonstrated above tris can be rendered in parallel)

I've been doing scene rendering in parallel for something like 8 years on Direct3D 9 (XNA) and classic OpenGL. Most of my current parallelization is explicit ordering of scene elements which allows me to prepare buffers/draw commands in parallel, and filling GPU buffers in parallel. If I ever move to Vulkan or D3D11/12 I'll be able to exploit parallelism more there. Those old APIs allow mapping GPU resources into user address space which in some cases already allow you to prep future rendering while existing operations are in flight.

It's also common for modern D3D and OpenGL drivers to create hidden threads in your processes that perform rendering operations behind the scenes while you issue your sequential commands from your threads. This effectively turns those APIs into secretly-parallel APIs, and the driver threads can exploit any parallelism hidden away like performing multiple buffer uploads at once or building command buffers in parallel.

Re: A Thought Experiment: Using the ECS Pattern Outside of Game Engines

#29
post #21

In the Clojure world, this used to be a popular way to structure backend apps: https://github.com/stuartsierra/component > Components provide some basic guidance for structuring a Clojure application, with boundaries between different parts of a system. Components offer some encapsulation, in the sense of grouping together related entities. > Each component receives references only to the things it needs, avoiding un…

Stuart Sierra components and ECS components are not really the same thing though. They share the name “components” but not thaaat much else.

Stuart Sierra Components are more akin to Unity’s behaviour components prior to their introduction of an ECS. They’re a way of encapsulating state which may have dependencies and has a lifecycle (needing to be started or stopped).

ECS components are purely blobs of (usually fine grained) state, the existence and combination of which in an entity creates behaviours (that is, the systems which implement the behaviour will dynamically do so for any entity that has the prerequisite components, but the components are just data).

I always preferred naming ECS components as “traits” (they are the traits that an entity has, eg “animated”) and the systems “behaviours” (they are the behaviours exhibited by entities that have certain traits).

Re: A Thought Experiment: Using the ECS Pattern Outside of Game Engines

#30
post #21

In the Clojure world, this used to be a popular way to structure backend apps: https://github.com/stuartsierra/component > Components provide some basic guidance for structuring a Clojure application, with boundaries between different parts of a system. Components offer some encapsulation, in the sense of grouping together related entities. > Each component receives references only to the things it needs, avoiding un…

Used to be? What replaced it? I used it in my last Clojure project, and I'm about to start expanding it further; should I replace it with something else?

It's fine, hasn't just been getting much press lately.
Post reply on HN