Why I removed Components from my Game Engine

preview_player
Показать описание

#gamedev #programming
Рекомендации по теме
Комментарии
Автор

For me even if ECS wasn't best for performance, I would still use it.
I spent a lot of time in OOP and the main hero of the ECS paradigm are Systems.
(Entities and Components are just details that can have any shape)

Systems help not to hide dependencies and I know any code that is running is inside of Systems and there are no hard to see links between components

When I come back to by code bases, I do not need to know hierarchies of objects referencing each other, since ECS provide flat architecture I look at the individual systems and know what they do and what they interact with.

QIZI
Автор

A lot of false dichotomies in this rant. You say that Systems are primarily for performance optimization and if you don’t need the performance then it’s unnecessary increasing complexity. This is all incorrect. Systems force developers to make explicit dependencies on the Components they care about and then to write focused code pertaining to just those components. Rather than having long complicated update logic that touches many different aspects of the game, a good ECS implementation will use several Systems, each doing a fairly small straightforward task. Like in your on fire example, you might have a flammable component and an on fire component. The PropagateFireSystem might find all flammable entities next to on fire entities and decides whether or not to also set those to on fire. Then the FireDamageSystem would take all thinks that are on fire and have a hitpoint component and start deducting hit points. Then a AssignDeadSystem marks any hitpoint entity with 0 points with a dead component, and so on. Coding this way is incredibly simple, not an addition of complexity that you claimed. This is just one of the few false dichotomies that you’re providing throughout the video.

saritsotangkur
Автор

This video confuses me a little, I get your point: there is no need to implement ECS every time, and I agree, you don't need it. But you also continuously implied that ECS is just an annoying meme of no value, while highlighting why your provided alternatives are still inferior to ECS (e.g. "hey look, you can compose this way instead, it still uses more memory than ECS, and it is also uglier than ECS, but... but hey! You don't need any of that! Probably!").

Again, I agree that you don't *need* ECS, as in, implementing a fully-featured ECS engine for your small indie game, including the features that you do not need, is most certainly not worth it. And while this video contains a lot of great advice for beginners, I feel your criticism of ECS seems mostly emotional, I'm just not seeing these "half-truths", I don't think anyone said that ECS was the only way to do composition, or that it's the only pattern that is good for designers, or that it's the only pattern with good performance. From my understanding, the main point of ECS is that it's a pattern that can be used as an alternative to OOP, it's not the end-all be-all of game development, it's just a good alternative to OOP, as it is more cache-friendly than OOP, while still having a nice design pattern, it covers all bases, even if you don't need it, it is a very general solution, just like OOP.

What you propose is to not stick with neither of these patterns, and act on a case-by-case basis, which is good advice, but that doesn't say there is anything wrong with ECS, the benefits are definitely there, even in your examples, it's just a question of scale.

deadvirgin
Автор

my youtube reccomendations be like:

yesterday: inheritance sucks
today : ESC sucks
tomorrow : your existence sucks

RenderingUser
Автор

The other advantage of ECS systems is for *fast querying* of entities based on which components they have. Your example had to do a linear search for onfire objects. An archetype based ECS would have it handled by partitioning and be proportional to O(number of archetypes + number of onfire entities). If not using archetypes it can be implemented by hierarchical bitmaps. You will want something like it if you have a lot of very specific properties that your entities can have

Also, the video does apply to handmade game engines, but not as much to when choosing an already made game engine with a mature ECS like Bevy, and comparing it to a mainstream one like say Godot which can be very object oriented. Chosing something like Bevy vs something like Godot is something that is strongly dependent on how you feel about composition vs inheritance

BosonCollider
Автор

To me the title is click bait. As you said, I can't see how your new paradigm isn't just replacing entities by entity array indices and components by entities. I totally agree that composition has nothing to do with ECS. But really in this video, you just switch from one way of implementing ECS to another that is simpler for your use case.

neperion
Автор

Big benefit of systems almost nobody talks about is testability - having well-defined dependencies means having well defined interface and responsibilities, and this makes maintaining solid automated test suite so much easier than most alternatives. Other takes on composition (say, dependency injection) cover that case, but come with their own drawbacks - in case of DI, it's often mix of memory fragmentation and performance overhead from multiple levels of indirection.

With a bit more complex take on systems (having update systems limited to updating one component only, and having all other updates go through event system) I got level of testability I'm personally happy with - everything can be automatically tested both in isolation and interconnected, without unnecessary overhead (a read-only rendering system doesn't need to be loaded at all for automated tests of game logic etc).

asmonull
Автор

I partially agree, though I won't detail my reasons.

Context is crucial. ECS can either streamline or complicate your project, depending on your objectives. I find ECS beneficial for networked games requiring deterministic simulations, as it centralizes data management, simplifying netcode. It also facilitates writing tests to guarantee consistent game logic replication. However, ECS isn't suited for every game type.

nobu-sh
Автор

your suggestion to store all the indices to various arrays in Entities is really just not good

For one, you lose the advantage of flexibility because you can't iterate over 2 units of data at once (assuming the arrays are contiguous and not sparse). As an example, let's say you want to iterate over the renderable draw texts, if you just iterate from 1 to the length of the draw text and index both the draw text and the renderable, the data you're accessing isn't necessarily related.

Two is you now need to manually manage and keep in sync the array with the rest of your entity pool. Effectively, you're manually performing an ECS algorithm

The thing about the mega approach is that it is literally an unoptimized ECS. You have all the data stored in one struct and flags that determine and interpret the meaning of that data, this means that you're 1. wasting memory, 2. having to iterate over the entire ECS to just get a few entities. I agree with you, this just isn't a big a deal as it seems. But also, it is sometimes a big deal, and when it is, you should invest time into making an ECS.

I think another issue with this approach is the lack of type safety from your data. Your entity stores absolutely everything, and from a glance, it can be difficult to gauge what a specific part of the entity is and whether a specific entity actually has the relevant data.

A possible solution without going towards a full ECS is just splitting out the big Entity struct into separate arrays which are of length max entities, or of the maximum amount that specific component can have. An index of 1 corresponds to the same group of data in every array, this is a balance between the big megastruct approach and an ecs. This lets you get some of the type safety back, but still has the issue of needing to iterate over everything since the array is sparse.

But honestly, an ecs isnt that complex of a thing. It's actually pretty simple if you're doing a sparse set based one, and it just overall makes your life a lot easier. Especially in languages without inheritance.

schelney
Автор

I would agree that ECS is not a golden bullet and a good programmer can write code which would be faster, though, it is not something any junior -middle programmer will be able to do. Also, I feel like you have a small misconception about how ECS works. This shows in the cache locality discussion and in the first example of "ignite all entities"
The problem with having an entity class, is that with time, it becomes a lot bigger. And in the code you showed as the first example, you iterate over the array of entities, meaning you get all the fields of the entity, except the two you actually need (aabb and flags). And what ECS does, is arranges data depending on the systems you have automatically, so a system iterates over arrays which only have the data that system needs. This can be a huge difference if you game has big entities, and most of the times, entities tend to grow a lot.

Also worth mentioning, that existing ECS systems differ quite a bit, and some of them can be faster to create new entities and slower on iteration and Vice versa

alexanderduk
Автор

Nice video! Glad to see a different perspective that offers practical solutions besides the mega-entity. The sooner we learn how to detect when we are over-engineering solutions, the better.

DylanFalconer
Автор

Thanks for this, I was hoping you could help though, how would you add custom behaviour to these entities, let's say I have an NPC that should teleport me when interacted with, where would that logic sit. It seems sort of impossible without using some kind of inheritance doesn't it? As I don't quite see how I could add a Teleporter object into my []Entity array

bertrodgers
Автор

I wonder: What's the threshold number of objects that justifies going for more threads?

KiaAzad
Автор

Thanks for a very good video!
Your resulting engine is quite similar to how we do things in the Flame game engine too. :)

FlameEngineDev
Автор

This was pretty well spoken brother! Lots of great advice here!

trixer
Автор

Thanks I really enjoyed your video/talk. I know nothing about ECS as I was just introduced to the acronym recently. You're very clear but the pace is a bit fast for me. No worries that's what re-runs are for. Now I have to find out what the term component means in this context.

maxwellsmart
Автор

hi, what theme do you use? it looks amazing and i wanna use it myself

ikyyntts
Автор

Great points in this video. The concept of "breaking down a paradigm into components and only using the components you need" can be applied on so many levels.

gamemakertim
Автор

Haha! Love the Periphery you were listening to on Spotify. Didn't realize they had new tracks out! Is Zagreus a reference to Hades (game)?

colincurrie
Автор

I always thought that composition leads to objects that have components - independent of ECS or any other architecture. This is just wording but it was confusing at first.

I think adding complexity is an interesting thing. For a small game project I worked on, I made a small framework which kind of made it possible to have game objects with components like in unity (without ECS). It has certainly added some complexity but focusing only on implementing the features that small project needed, it made development much faster and easier than without the abstractions.

Having hidden complexity can enable you to be much faster in developing a product by using some good library. Sure, it will also cost you something but it might just make it that much easier to implement all the necessary features for your project.

The component based architecture unity uses, enables lots of inexperienced programmers or even artists to make games they could not make without it. They probably won't have the most performant product in the end but they have something working. And by using unity or any other engine they probably use a lot more hidden complexity than you even would be able to produce with your own engine/framework.

I think the composition over inheritance approach of ECS implementations is the most important factor. This makes engineering an object easier for less experienced people, because it forces them to think in different components instead of the big bloated player object which can do everything. At least if they try to keep to the principles. My take is that this is the biggest selling point of It, because it sounds so easy and straight forward to compose a complex game object using relatively simple components.

And people somehow seem to think that is directly tied to having an ECS, which you correctly showed it is not.

MaviLeb