How fine grained should a component be for a component-based game entity?

Started by
6 comments, last by Telastyn 15 years, 9 months ago
Hi all, So inspired by this article (http://cowboyprogramming.com/2007/01/05/evolve-your-heirachy/), I set out to work on a component-based entity system for my FYP (as part of a software engineering thingy overall). In doing the project, I run into some interesting scenarios - for instance, how fine grained a component should be, and should they communicate with each other, and how do they communicate with their parent entity (and the other way round). For example, things which I find the component system really helpful for is a moving component - as all it needs its the parent's position, facing and so on (which I assume that all entities should at least have, and the component is fully isolated by itself - it does not need to communicate with any other objects (another component should take care of the collision detection, which is what I did) However, there are some things which I find using the component system questionable. For instance, the next project I work on is a tile-base game, a match-4 variant basically, and well, though it may be overkill to use a component-based system, I went ahead to use it to see how useful it is and whether it is adaptable. The first problem I run into is components that stores nothing but data. That's fine, I reason -- the existence of the component allows the entity to interacts with the world. I am using a recursion function to detect whether tiles are connected - do I use a single recursive function which works on the components (that is, extract the component's data out) or do I split the recursive function into the components (that is, a component that checks it neighbour, and that invoke that neighbour to check its neighbour, and finally it itself will know whether it is connected). I opt for the former choice as the code is easier to understand; but this got me thinking - all that is needed for this case is the type of tile. Component-based design, as it is, coupled both data and logic. Is it a good idea to break them apart? The second problem is with entities with many states - say, an enemy entity with an AI FSM. Is the AI one big component? Many components and communicating with each other? One big-daddy component with many sub-components? The third problem is inter-components communication within an entity - For example, the player-controlled entity has a Hit Points -- where does it go? I could have a DamageableComponent and store the Hit Points there, and it means that all sort of modules will be communicating with that component - UI, game logic and etc. Of course, to sum up, I have two ideas in mind, and I am not sure what the pros here think... 1) Decouple logic and data from components - components should only have logic, and data should use another system, such as a hash-table or such, and is handled the same way as components (we could call it properties). Hence a component work on the properties data stored inside the entity. 2) Let data and logic be stored within the component, but use an event-based system, or observer, to update the component and let the component updates other real-time. 3) Allow components to have components (to solve the check if tiles are connected problems) What I am doing now is I am having an entity object which stores nothing but components, and another logic layer which stores the entity object which work on the components; I am not sure if DIP or something else is violated this way, but this looks like the easier way out. I guess the crux is -- how do you handle a component-based entity when a piece of game logic that needs to know many of the entity's properties?
GamesTopica.Net- http://www.gamestopica.net
Advertisement
You change your design so it doesn't need to know about most of the entity's properties... (or it only needs to know the public ones, then pass a weak pointer/reference and let it access wily-nily)

Personally, I think current (mainstream) programming languages are not well formed to do component style designs. A type system that allows some sort of mapping (something that can move requires the entity have a position [and the position is variable <foo>]) would make a lot of these problems a lot easier.
Quote:Original post by Telastyn
You change your design so it doesn't need to know about most of the entity's properties... (or it only needs to know the public ones, then pass a weak pointer/reference and let it access wily-nily)

Personally, I think current (mainstream) programming languages are not well formed to do component style designs. A type system that allows some sort of mapping (something that can move requires the entity have a position [and the position is variable <foo>]) would make a lot of these problems a lot easier.


Can you go into more detail about this please? Your meaning is not quite clear to me.

EDIT - I was reading your journal which I should really do more (i could have mentioned scala :p) and it looks like - i am unsure - that one of its design goals is to handle the issue you note above. I am not sure but it seems like you are trying to extend generics to support parameters? I would go so far as to venture that you are trying to make a language that supports dependent types?
Quote:Original post by Extrakun
1) Decouple logic and data from components - components should only have logic, and data should use another system, such as a hash-table or such, and is handled the same way as components (we could call it properties). Hence a component work on the properties data stored inside the entity.

2) Let data and logic be stored within the component, but use an event-based system, or observer, to update the component and let the component updates other real-time.

3) Allow components to have components (to solve the check if tiles are connected problems)

I guess the crux is -- how do you handle a component-based entity when a piece of game logic that needs to know many of the entity's properties?

I am using an outboard component system, but in Python, which is of course a little more flexible. In my case the components handle all logic, and the shared data is stored directly in the entity itself. Each component does hang on to component-specific data, of course (i.e. the graphics component stores the model data, rather than placing it in the entity).

This seems to be working well so far, but I haven't finished the game yet, so we will see ;)

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

#2. A component represents a feature or function for an entity, so it needs to know about data and logic. Also, properly designed, an event-based system (through a combination of methods and messaging) will handle these cases you are concerned about.

Admin for GameDev.net.

Quote:Original post by Daerax

Can you go into more detail about this please? Your meaning is not quite clear to me.

EDIT - I was reading your journal which I should really do more (i could have mentioned scala :p) and it looks like - i am unsure - that one of its design goals is to handle the issue you note above. I am not sure but it seems like you are trying to extend generics to support parameters? I would go so far as to venture that you are trying to make a language that supports dependent types?


For those of you who don't read my journal, Daerax is referring to my current hobby project. It is a toy language I started work on after reading one too many of these component based entity architecture threads.

While one element is providing more flexibility to generics, that is mostly focused around the problem currently in C# generics where you can't specify a generic argument which is 'numeric'.

And I'd kinda like dependent types (assuming wikipedia's description is accurate) but I'm just talking about facilities to assist component mixing.


My toy language provides two facilities which are the sort of thing I think would benefit component systems. The first of which is more applicable to the position/move example.


1. Mix-in rather than traditional inheritance.

public struct Coordinates{    public int x;    public int y;}public class Positionable{   protected Coordinates position;   // Other methods that work with a specific position which are    //   not applicable to Coordinates themselves.}public class Movable{   protected abstract Coordinates position;   public void Move( Coordinates to ){        // some check to see if the move is possible        // maybe something to throw an event        position = to;   }}public class Orc: Positionable, Movable {}public class Box: Positionable, Movable {}



2. More flexible free functions

public class Positionable{   public Coordinates Position;   // Other methods that work with a specific position which are    //   not applicable to Coordinates themselves.}public class Tank: Positionable{}public class Horse{    public Coordinates Position;}public void move(Positionable Actor, Coordinates Target){   // Same sort of move function.   Actor.Position = Target}public void move(Tank Actor, Coordinates Target){   // Tank specific rules   //  ...}// move will be overloaded here, and act like a virtual method.// Called with Tank, it will call the second method since it's//  more specific.// // In my toy language at least, move(someHorse,someCoords) will work nicely.//  Methods can then be written that work with an interface rather//  than explicitly requiring inheritance.



The first is really better for the position/move problem. The abstract field simply provides an interface that must be supplied to use the class. And the mix-in inheritance lets you toss pieces of an entity together without having to re-expose member functions.

Ah yes. Well I would be interested in playing with your language.

In C# 3.0 Extension methods were introduced. Which coupled with interfaces allow you to get most of the functionality of mixins.
Quote:Original post by Daerax
Ah yes. Well I would be interested in playing with your language.

In C# 3.0 Extension methods were introduced. Which coupled with interfaces allow you to get most of the functionality of mixins.


Yup, most.

And it'll be available for folks to play with in a few months when it looks more like a buggy amateurish research compiler and less like a steaming pile of bugs which takes source code and gives you more bugs in return. [grin]

This topic is closed to new replies.

Advertisement