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'...


9

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

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

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 ...


3

For states, I usually use Enums, and then do a switch statement within the Update method. Enabling/disabling components is probably easier than adding/removing them. If you need to listen for or be ready to execute a method that should only happen within a specific state, check the state at the start of the method. If the file gets too long and confusing, ...


3

Note: This has turned out to be a long answer. If you just want to see the main idea, scroll to the Main Answer heading I have recently come across almost the same issue. My home-baked framework is more traditional in the sense that components have a few methods, but I think I should still be able to help. The real issue you seem to be dancing around can ...


3

If you know what an entity would require to wrap it up in an object, ECS doesn't stop you from doing the same in an iterative way. In a system, if an entity has the required components, the target components will be updated. If an AI component requires other components, it will only be updated if the entities has them. If it does not, a different behaviour ...


3

Okay, disclaimer: this has gone completely overkill. But it was a lot of fun to put together! The end product looks like this: Object *target = WorldMap.getObject(pos,facing); target->dispatch([&](components::EnemyTag &, components::Health &h) { h.attack(weaponStrength); }); dispatch takes in any function or function object (here a lambda)...


3

First of all, there is no "right" or "wrong" way to structure a game's software architecture. Just ways which work or don't work for you. Usually you wouldn't nest components. What you would do instead is nest entities by making them parents and children of each other. The Universe entity has many Planet child-entities A Planet entity has many Building ...


3

I think you may be overthinking this. The point of ECS is to be simple: An entity is nothing more than an aggregate of components. A system is only interested in a subset of those components. For example: A rendering system would only be interested in Transform and Graphics data components,and a physics system would be interested in Position, Motion and ...


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