0
\$\begingroup\$

What do I need to know in order to implement ECS in a video game? I'm developing a video game and so far I wasn't using any complete architecture, I was just using inheritance but I don't like it because the code became messy. So far, I've seen so many articles in which the subject is treated, but I don't understand how to implement it. All what I get is there is that a component is a bunch of information, an entity is a bunch of components, and each system deals with the logic of its own components. But I've got a question about it, they're a bunch of IDs, how do those IDs store data? How to retrieve data from it? I've got a problem, since I was trying to implement components, in order to do it all what I did was declare a parent abstract class in which I'd store members of that class and then I would be able to access to those members. The problem came when I was trying to declare children of that abstract class, since that parent class can't have all the members of all the another components (and I need a way to iterate all the components in a vector). So... I want to keep the things as simple as possible. Any advice for someone like me? How can I implement ECS in a simple platformer? Please, Thanks in advance!

\$\endgroup\$
  • \$\begingroup\$ ECS will not prevent your code from being messy. Only good programming habits can do that. \$\endgroup\$ – Almo Jul 29 '18 at 22:47
  • 3
    \$\begingroup\$ There's not just one way to implement ECS, but many ways. As long as you have something in your game that could be called an "entity" something that behaves like a "component" and some kind of "system" that acts on them, you've got an ECS system. That could mean your components all derive from a base with some common methods like Update and your entities each store a list of them. Or it could mean that you store a vector of each distinct component type and an ID-to-component lookup structure to quickly find components attached to the same entity in other vectors, etc... \$\endgroup\$ – DMGregory Jul 30 '18 at 0:12
  • 1
    \$\begingroup\$ Just because you're not using ECS and are using inheritance doesn't mean you're not using well-defined architecture. OOP with inheritance can have very well-defined architecture. You just have to know how to use it properly. \$\endgroup\$ – Almo Jul 30 '18 at 2:41
  • 1
    \$\begingroup\$ @Joza100 "you need to copy a lot of code" Why is it so? \$\endgroup\$ – Vaillancourt Jul 30 '18 at 13:01
  • 1
    \$\begingroup\$ Just because you can make a mess doesn't mean you have to. You're just being a fud about tech you don't like. I've written several games using inheritance and OOP techniques, and had no architecture problems. I've worked on AAA games that used inhertiance and we had no problems with architecture. I've seen it be a hideous mess, too. Like any tool, inheritance can be used well or poorly. In the end, programming is engineering, and it's more important to be pragmatic and solve the problem at hand than to adhere to some rigid idea of how things should be done. \$\endgroup\$ – Almo Jul 30 '18 at 14:25
2
\$\begingroup\$

Keep in mind that ECS is at its core not an object-oriented design pattern. It is more suitable for structures and functions.

[entities are] a bunch of IDs, how do those IDs store data?

In an ECS-by-the-book architecture, entities do not store any data. Components store data. Also, neither entities nor components contain any logic. All logic is in the systems.

So you don't have an entity with a collision box. You have a vector of collision box components and some data structure which maps IDs to collision boxes (the article mentioned in the question calls these "Component Managers"). What kind of data structure is an optimization problem. But a good default solution is to use std::map<int, CollisionBox*>. You then have a CollisionSystem which detects and handles intersections between those collision boxes.

Sometimes it can be useful when components contain the ID of the entity they belong to so you can more easily find other components of the same entity. But not all components will need this.


However, this is a very C-ish style of creating an ECS system. If you feel more comfortable with a more object-oriented design, then you can also have a class Entity which contains pointers to all its components. You can even have a class hierarchy of entities which differ by what components they have and how they initialize them.

But the concrete instances of the components should be stored in large arrays (which you can abstract as a std::vector if you like) with one array for each type of component. Systems should operate on these arrays whenever possible to benefit from memory locality (iterating through an array is much faster than dereferencing a pointer).

Just don't forget about the basic principles of ECS:

  • Components contain all the data
  • Systems contain all the logic
  • Entities say which components belong to each other
\$\endgroup\$
  • \$\begingroup\$ By the way, the component doesn't need to contain the ID of the entity. Simply, instead of giving the system the components it needs to operate, check if the certain entity has those components and then just send the entity to the system. That way the system will have access to all the components inside the entity. Also, entities don't just have to be IDs. They can be a class that stores components. \$\endgroup\$ – Joza100 Jul 30 '18 at 13:01
  • \$\begingroup\$ @Joza100 The problem with storing components inside your entities is that you lose the memory locality advantage which makes the ECS pattern so performant. But when the mechanics of your game aren't the bottleneck, then that's of course a non-issue. \$\endgroup\$ – Philipp Jul 30 '18 at 14:49
0
\$\begingroup\$

Entities don't have to be a bunch of ID's. Just create an Entity Class that will contain a list of components and that will have some methods that will help you add, remove, get, and check if the entity has certain components.

For component, just make an empty interface called component and use it for polymorphism. That way make more classes that extend Component and store data in them. Put them in the list of components that you have in your entity.

Then make systems. The way systems work is, you give your entity to your system and the system checks if that entity should be operated in that system by checking if the entity has components that the system requires. If yes, retrieve the components from the entity and make the logic in some kind of an update method that will run every time your game updates!

Also, you asked how the ID can store those components. Well, it doesn't, but in your engine class, you just store it in a HashMap. The hash map has the entity ID as a key and the List of components as the value, but as I said, better just make an Entity class that will contain the ID and the list of components! It's easier

There are many ways you can do this, this is just how I did it. There is also one tutorial series on Youtube by BennyBox who makes a 3D engine in C++. There he uses ECS and he even programs the ECS system there. You can do the rest of the stuff by your way and just copy his ECS if you don't want to make your own or the way I explained.

Here is the link:

https://www.youtube.com/watch?v=Y6he35HfDmA&t=1183s

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.