23

If you are going to be storing the Components in a collection all together then you must use a common base class as the type stored in the collection, and thus you must cast to the correct type when you try to access the Components in the collection. The problems of trying to cast to the wrong derived class can be eliminated by clever use of templates and ...


17

Chewy has it right, but if you're using C++11 you have some new types you can use. Instead of using const std::type_info* as the key in your map, you could use std::type_index (see cppreference.com), which is a wrapper around the std::type_info. Why would you use it? The std::type_index actually stores the relationship with the std::type_info as a pointer, ...


14

Mick West's article explains the process of linearising entity component data, in full. It worked for the Tony Hawk series, years ago, on much less impressive hardware than we have today, to greatly improve performance. He basically used global, pre-allocated arrays for each distinct type of entity data (position, score and whatnot) and references each array ...


11

The simple version: don't. One could argue that you have perhaps a slight misunderstandings about how to build an ECS (why would you sent a list of Entity* to a system to update? the System is supposed to have its own self-contained collection of the components it cares about, and the global entity list should barely ever even be used... a "true" ECS doesn'...


8

In a "pure" ECS, your entities consist of just a unique ID, which shared among its components. For example you may have these entities: Entity ID 123, it is drawn and moved Entity ID 234, which is only drawn Thus you'll have the following component collections: Drawn components: <123, 234> Moved components: <123> There is no need to filter in this ...


8

I will risk and post almost-opinion based answer. What Unity is missing is decopled "system" element. It would be much nicer to have "Component-Entity-System" instead of current "Component-Entity". That is because of the problems you mentioned. The problem of communication you have mentioned can by solved by adding System. Unity Component, holds both, data ...


7

You have essentially designed a static object system with a pool allocator and with dynamic classes. I wrote an object system that works almost identically to your "assemblages" system back in my school days, though I always tend to call "assemblages" either "blueprints" or "archetypes" in my own designs. The architecture was more of a pain in the butt ...


7

The entity component system (ECS) is great. There are plenty of misunderstandings about it though. For example, it's perfectly fine to use event/messages in an ECS. People often think you're supposed to completely avoid inheritance too. Also not true. The ECS methodology is just a strategy for avoiding issues that come with a large hierarchy of inheritance. ...


7

Having local lists for each system will increase memory usage for classes. It's a traditional space-time tradeoff. While iterating through all the entities and checking their signatures is straight to code, it may become inefficient as your number of systems grow - imagine a specialized system (let it be input) that looks for its probably single entity ...


7

Merging systems, such as collision and collision response, is a bad idea. The reason being that there can be many different responses to collisions: Physics based, and game-logic based. In most game engines I have seen (ECS and non-ECS and all the greys in-between), there is some kind of inter-system communication system, because this is what makes the ...


7

One of the big reasons some ECS proponents favour a strict separation of components and systems is that it helps architect game functionality in a data-oriented style. In the ideal data-oriented flow, all your major systems work like particle systems: churning through big batches of data at a time that all need the same kind of operation performed on them. ...


7

Games typically approach this type of issue using a transformation hierarchy. In this model, each entity can be treated as a "child" of a "parent" entity. The entity's local position and orientation components are interpreted to be relative to the position and orientation of the parent. Parent entities may in turn have their own parents, grandparents, etc.,...


6

Partly to allow data-driven operations, and partly because an ECS is a specific subset of all possible component-based designs. A main point of component-based approach to aggregation (be it ECS or another use of components) is to allow you to reconfigure game objects without needing a recompile. You have an editor that your designers and game scripters ...


6

Do the simplest thing that works, especially early on. If you've ever seen videos of triple-A titles in alpha, you'll know how slow / buggy they are. This is normal; in fact, it's desirable. And it's often because they used the naive solution to problems. Agile development philosophy states Refactor Mercilessly; I couldn't agree more, from experience. ...


5

There's an approach that is worth considering where each system owns the components associated with itself and the entities only refer to them. Basically, your (simplified) Entity class looks like this: class Entity { std::map<ComponentType, Component*> components; }; When you have say a RigidBody component attached to an Entity, you request it ...


5

This doesn't directly answer the question but, from the sounds of it your question and the information you're wanting seem to differ a little (at least to me). So this "outlook" might help connect them. Abstractions commonly lead to generalizations so you can prepare for future unknowns. This is what Unity does since it knows barely anything about the type ...


5

TL;DR Entities SHOULD NOT auto-register to systems based on component signatures; prefer instead to explicitly declare component sets/nodes to register your entities to systems that operate on specific component signatures. It’s been almost a year since I’ve asked the question, and I’ve played with both approaches to take a step away from theory and see how ...


5

One nice thing about systems in an ECS architecture is that they don't all necessarily need to follow the same structure of for(int i = 0; i < entities.length; i++) process(entities[i]); and then implement process(entity) as if there would be no other entities in the universe. If there is a smarter way to process entities than sequentially in natural ...


4

You have various implementation issues and some misunderstandings either about C++ or what ECS is supposed to do. template <class T> std::vector<unsigned int> getEntitiesWithProperty() { std::vector<unsigned int> ret; auto key = std::type_index(typeid(T)); std::unordered_map<unsigned int, PProperty*> map = data[key]; ...


4

They should use the same movement component for both, if the movement component is velocity. However, the systems that modify the velocity will be different. The ball will use the physics component to bounce off the paddles and walls, where the paddles will use the mouse/keyboard input component to move. So the physics system will be modifying the movement ...


4

What you've done is re-engineered C++ objects. The reason why this feels obvious is that if you replace the word "entity" with "class" and "component" with "member" this is a standard OOP design using mixins. 1) you lose the dynamic nature of pluggable components, which was created specifically to get away from static class construction. 2) memory ...


4

I often see people over-engineering event systems, my advice would be to keep it simple. For a simple game an enum suffices to identify events. For games with a large amount of events from different code modules and scripting functionality it will become a burden because it is not extendable (and increases compile time). Imagine you added a script system ...


4

I suppose that you're really asking now, post-edit, how you can use the entity ID's as indices into your component vectors without there being gaps in the component vectors. The simple answer is that you can't. You really want an associative container for your components, like an std::map or std::unordered_map, but barring that, if you insist on storing your ...


4

Reducing cache misses doesn't need to mean getting rid of them entirely, so we do need to be wary of "making the perfect the enemy of the good enough" After all, the absolute worst performance your game can have is a game that never runs at all because you're still working out every detail of the best possible ECS. If you store all your mesh rendering ...


Only top voted, non community-wiki answers of a minimum length are eligible