Questions about Entity-Component Systems

Started by
7 comments, last by Juliean 11 years ago

I have a couple questions regarding entity-component systems. From my reading, it seems that components are to be "data only". Does this mean they should not contain any functions? Say, for instance, I have a "movement" component. This would be given to entities that are able to move, and it would contain variables such as speed, acceleration, max speed, etc. Would it not make sense to give this component the functions that deal with with collision detection and updating position?

Second question. This entity-component system is aimed to replace the inheritance structure of traditional OOP. Does this mean inheritance should be avoided all together when using such a system, or are there cases where it can be used to create a sort of hybrid system? I can imagine using inheritance with the components themselves (such as when some objects require different types of physics calculations).

Third question. In implementing an entity-component system, what does this actually do to the compiled program? As opposed to a traditional inheritance structure, does the compiled program take up more hard drive space? Does it take more processing power to run? Is there more overhead? If so for any of those, by how much?

Edit: Fourth question. What would warrant a project to make use of an entity-component system over a traditional inheritance structure? Is it something that should be used without exception, or is it really only beneficial for games with a large scope and with many programmers working on it?

Advertisement

I would assume that at the very least any Component would have to inherit from an IComponent interface and any Entity would inherit from an IEntity interface. But that's all.

Beginner in Game Development?  Read here. And read here.

 

My understanding is that components really only had 'get' and 'set' style functions. It is the Systems that are aware of how to manipulate such data. In my current project (still planning it) I simply have three base interfaces: ISystem, IEntity, and IComponent.

I store your 'movement' component in a 'CSpacialComponent' class that contains both an entity's spacial position but it's velocity, and acceleration. It also stores the same values for the object's rotation in Euler angles (that is angular displacement, velocity, and acceleration).

I have a couple questions regarding entity-component systems. From my reading, it seems that components are to be "data only". Does this mean they should not contain any functions?

There's many different styles - some are data only, and are operated on by 'systems', but others are more like traditional classes.

This entity-component system is aimed to replace the inheritance structure of traditional OOP. Does this mean inheritance should be avoided all together when using such a system, or are there cases where it can be used to create a sort of hybrid system?

The "traditional" inheritance structure comes from the fact that in the 90's, everyone sucked at / misunderstood object oriented design.
In good OO code, composition is much, much more common / important than inheritance (see "composition vs inheritance" on google). In the 90's, it was the trend to use inheritance for the purposes of code re-use, which frankly is wrong. This misuse of OOP has slowly been declining over the past decade.
"Component systems" are very similar to the OO concept of "composition", which should be preferred over inheritance by default. You can still use inheritance when necessary, but in proper OOD, it's not often really necessary.
I've considered using inheritance within components, but always backed off from it, choosing to either use multiple components or to make the distinction in a data-driven way.

This is partly because it would require a more complex system to find components. As it is, I can look up components on an entity by type. But with inheritance I would have to check every component to see whether it might derive from the one I was looking for. Then there's the possibility of multiple components of the same base type - which one did I want? This type of confusion is exactly why I went for components over inheritance in the first place.

I have a couple questions regarding entity-component systems. From my reading, it seems that components are to be "data only". Does this mean they should not contain any functions? Say, for instance, I have a "movement" component. This would be given to entities that are able to move, and it would contain variables such as speed, acceleration, max speed, etc. Would it not make sense to give this component the functions that deal with with collision detection and updating position?

There are different ways to implement that. One older implementation would be using components that do also implement logic and function, while it is suggested to store the data in the entity itself (though I wonder how that might work, anyways). The other solution is really having the components be just data containers, and have the logic handled by systems. Systems usually search for entities with a given set of components - transform and material for a render system, bounding volume and mass for a physics system. These are just examples, I would suggest you to break systems up a bit more, plus an advanced physics system might better not use entities at all, but have the entities store some reference to a physics body instead and have a system that syncs those.

Second question. This entity-component system is aimed to replace the inheritance structure of traditional OOP. Does this mean inheritance should be avoided all together when using such a system, or are there cases where it can be used to create a sort of hybrid system? I can imagine using inheritance with the components themselves (such as when some objects require different types of physics calculations).

Case and point, with a clever entitiy-component-system system you will not need any or much inheritance at all. What for? Would you inherit components, to add some sort of additional data? Make another component instead. Would you inherit systems, to add some sort of behaviour? Make another system instead. The only good reason to use inheritance in such a system is if you wanted to restrict some components so that each entitiy can only have eigther one of them. Then you would make something like a "BaseLight" component without any data at all, and derive your actual type of light from it. I'm not so sure if this would make sense eigther, while this would work excellent from theory in my implementation, pulling out the special data might be a problem. It would probably require some sort of type attribute for the BaseLight component and a switch statement to determine the actual type. Not very pretty, if you ask me. So no, after all, no real need for inheritance here, unless you REALLY want to programmatically restrict some components in a 1:N relationship (this would work in my implementation since every component gets a certain ID associated with it, thats the key with whom they are stored to the entity - if I'd derive from a BaseXXXComponent, all childs would get that same ID to, so only one of them could be assigned to an entity at the same time).

First point

I gravitate towards keeping components as pure data and having systems provide implicit, automatic logic. Among other things, it makes inter-component dependencies much easier, as a system (and thus a task) requiring more than one component type will ignore entities that are inappropriate.

To use your example of a Movement component, you propose lumping position, velocity, and collision detecting together. The problem with this is that it enforces rules that don't need to exist, such as "every entity with a position is movable" and "every movable entity is collidable". You should split it up into three separate components with three separate domains of data:

  • Position
  • Velocity
  • Collision (shape)

The systems that you should use are:

  • Movement (adds velocity to position)
  • Collision (checks between collision shapes at positions)

As you can see, entities don't need to be movable or collidable to exist spatially, simply give them a Position component. This is useful for purely aesthetic static objects. Entities also don't need to be collidable to move, and don't need to move to be collidable. The latter is useful for static platforms and obstacles, while the former can be used for dynamic background props.

The key thing is that dependencies are automatically resolved if you have a system to detect when a system's desired component group is formed or unformed, registering and removing that entity from that system.

Second point

Components should all derive from a simple base class that holds the entity that component is part of. I'd avoid any deeper inheritance than that. You can use inheritance when designing your entities; for example, a robot chicken derives from a chicken class and adds a Robotic component (a bit contrived, but you get the idea).

Third point

The change in executable size will be negligible or even beneficial if you move entity definitions into data. In terms of runtime performance, entity-component-systems are easy to parallelize because, generally, each system operates on each entity independently.

"So there you have it, ladies and gentlemen: the only API I’ve ever used that requires both elevated privileges and a dedicated user thread just to copy a block of structures from the kernel to the user." - Casey Muratori

boreal.aggydaggy.com

Hello,

Everyone had pretty good inputs on the topic. I just want to emphasize that components should have functions... I always see people saying that components should be purely data related without any functions. It's what the functions do that needs to be addressed. If you are sticking with the more "recent" approaches to building a component-entity system, then functionalities of a component should not posess logic that modifies the data directly. I do not see any drawbacks of having functionalities that help setup the data. For example, if you have a "renderable" component, perhaps one of the functions parses a file to create the vertex/index buffers. If you have a "transformable" component, you could have functions that can rotate, translate, scale the underlying matrix data. These functions help set the data up. The logic on the other hand would be handled by a system, which would most likely call upon those component functions to modify the data.

I do not see any drawbacks of having functionalities that help setup the data. For example, if you have a "renderable" component, perhaps one of the functions parses a file to create the vertex/index buffers. If you have a "transformable" component, you could have functions that can rotate, translate, scale the underlying matrix data. These functions help set the data up. The logic on the other hand would be handled by a system, which would most likely call upon those component functions to modify the data.

At least your first example vialotes not only the http://en.wikipedia.org/wiki/Single_responsibility_principle, but would make your "renderable" component quite inflexible. If you want to change your file format, you have to change the renderable component, also if you want to switch the underlying API. But most of all, the "renderable component" should neigther be responsible for loading a file, nor a texture, nor anything else. That is the responsibility of your graphics libary, if not even a special file loading libary.

As for the functions that rotate, translate, scale... except for the rotation, that is not even necessary. These functions won't do nothing more than modifying the 3 respective scalation/translation fields of the matrix, at least for the rotation it is a bit more complicated so that would make the most sense, if any. I also prefer to have "transform" seperated into components for translation, rotation and scale, and store the values arbitrary, but thats probably a matter of choice.

This topic is closed to new replies.

Advertisement