Followers 0

## 32 posts in this topic

I'm developing a turn-based strategy game using a component based game engine and have been wondering how to structure my components.

There are quite a lot of collection components in my game. E.g. an Army contains many units. Is it suitable to have an ArmyComponent containing many UnitCpmponents? Is that a suitable level of abstraction for a component?

Another thing I've been considering is the level of abstraction for the buildings I'll have in the game and also connected properties. A player can create a farm, which produces food. A player can also create a barrack to construct units, but this building also increases the offense points of troops by 10%. These types of properties can obviously change (although not likely that any other building than a farm will produce food), and as such this should be customizable easily. My question is what level of abstraction the components should be? Should there be a BuildingComponent, ProductionComponent, and ResourceComponent? Or should there be a FarmComponent, ProductionComponent and FoodComponent? Am I making my components too granular?

I obviously want to create a flexible system, but I don't want to over engineer either. Most buildings will be static, while their properties will change. That's why I'd like to hear your opinion of how you'd structure these relationships using a component based engine.

One more thing, and this question is about sub systems. I intend on making the sub systems handle the logic, and only have the components store data. Does anyone have some tips & tricks regarding how to think about sub systems? I've read that one should aim for a 1:1 relationship between components/sub systems, I am not sure this would be the case for me given my current setup with regards to my granularity of my components.

2

##### Share on other sites

There are quite a lot of collection components in my game. E.g. an Army contains many units. Is it suitable to have an ArmyComponent containing many UnitCpmponents? Is that a suitable level of abstraction for a component?

A unit may logically belong to an army, but that doesn't mean that a unit object needs to literally be contained by an army object. Components on components is just asking for trouble anyway. A better approach would be to either have an ArmyID property on your UnitComponent, that indicates which army it belongs to, or have a separate ArmyUnitComponent altogether which contains the ArmyID. In either case, units don't necessarily have to belong to an army if the ArmyID is invalid (or the ArmyUnitComponent isn't present in the latter case).

Another thing I've been considering is the level of abstraction for the buildings I'll have in the game and also connected properties. A player can create a farm, which produces food. A player can also create a barrack to construct units, but this building also increases the offense points of troops by 10%. These types of properties can obviously change (although not likely that any other building than a farm will produce food), and as such this should be customizable easily. My question is what level of abstraction the components should be? Should there be a BuildingComponent, ProductionComponent, and ResourceComponent? Or should there be a FarmComponent, ProductionComponent and FoodComponent? Am I making my components too granular?

This is just my opinion, but I would probably design the components around how they affect the gameplay as a whole, rather than the specific building or object to which they are tied. For instance, a farm may produce food, but what if you eventually want to have some other object that produces food? Instead of creating a FarmComponent and then trying to adapt or pigeonhole that into some other object later on, just create a ProducesFoodComponent (not a great name but you get the idea) that you can add or remove to just about anything in order to increase food production in your game system by +X%. Same thing with unit offense and production. You get the most flexibility by designing components so that they can be added to just about anything and behave as you expect they would, while understanding that might not always be possible.

One more thing, and this question is about sub systems. I intend on making the sub systems handle the logic, and only have the components store data. Does anyone have some tips & tricks regarding how to think about sub systems? I've read that one should aim for a 1:1 relationship between components/sub systems, I am not sure this would be the case for me given my current setup with regards to my granularity of my components.

It isn't a hard and fast rule that there be a 1:1 correlation between components and systems. That just tends to be close to what happens when you move your logic out of the components. However it's entirely reasonable for components to simply be tags, in which case they wouldn't have any logic of their own, or perhaps for multiple systems to interact with the same component (however in that case you'd want to question whether or not that component can be split apart).

Edited by Zipster
2

##### Share on other sites

There are quite a lot of collection components in my game. E.g. an Army contains many units. Is it suitable to have an ArmyComponent containing many UnitCpmponents? Is that a suitable level of abstraction for a component?

A unit may logically belong to an army, but that doesn't mean that a unit object needs to literally be contained by an army object. Components on components is just asking for trouble anyway. A better approach would be to either have an ArmyID property on your UnitComponent, that indicates which army it belongs to, or have a separate ArmyUnitComponent altogether which contains the ArmyID. In either case, units don't necessarily have to belong to an army if the ArmyID is invalid (or the ArmyUnitComponent isn't present in the latter case).

Am I trying to hard to create a classic domain model? Are there any "best practises" with regards to e.g. collections when using a component based engine? Is it more common to see denormalized data structures in component based engines?

Another thing I've been considering is the level of abstraction for the buildings I'll have in the game and also connected properties. A player can create a farm, which produces food. A player can also create a barrack to construct units, but this building also increases the offense points of troops by 10%. These types of properties can obviously change (although not likely that any other building than a farm will produce food), and as such this should be customizable easily. My question is what level of abstraction the components should be? Should there be a BuildingComponent, ProductionComponent, and ResourceComponent? Or should there be a FarmComponent, ProductionComponent and FoodComponent? Am I making my components too granular?

This is just my opinion, but I would probably design the components around how they affect the gameplay as a whole, rather than the specific building or object to which they are tied. For instance, a farm may produce food, but what if you eventually want to have some other object that produces food? Instead of creating a FarmComponent and then trying to adapt or pigeonhole that into some other object later on, just create a ProducesFoodComponent (not a great name but you get the idea) that you can add or remove to just about anything in order to increase food production in your game system by +X%. Same thing with unit offense and production. You get the most flexibility by designing components so that they can be added to just about anything and behave as you expect they would, while understanding that might not always be possible.

In this case, would building be an entity connected to a player via a PlayerBuildingComponent (or such)? I'm having difficulty actually separating entities and components at times, usually when relationships are involved (which I have quite many of).

Concrete example of how it works in my game: Say a player has x farms. There is no interest for the player to see these farms as unique, so I would group them into some data structure which says: BuildingType: Farm, Amount: x. But then behaviour needs to be added to this entity (or component, depending on your answer to the above question), so we add ProducesFoodComponent to this entity. Am I on the right track with regards to making the Building an entity in this case, and then linking this entity building to my player entity via a PlayerBuilding Component on either the Player or Building entity? If I don't do separate the building data structure into an entity, I'll get components having children of components, which does not seem right.

One more thing, and this question is about sub systems. I intend on making the sub systems handle the logic, and only have the components store data. Does anyone have some tips & tricks regarding how to think about sub systems? I've read that one should aim for a 1:1 relationship between components/sub systems, I am not sure this would be the case for me given my current setup with regards to my granularity of my components.

It isn't a hard and fast rule that there be a 1:1 correlation between components and systems. That just tends to be close to what happens when you move your logic out of the components. However it's entirely reasonable for components to simply be tags, in which case they wouldn't have any logic of their own, or perhaps for multiple systems to interact with the same component (however in that case you'd want to question whether or not that component can be split apart).

Ok. I'll think some more about subsystems and see if I come up with any more questions regarding this issue.

Thanks for the answers so far. Really helpful having someone to discuss these issues with!

0

##### Share on other sites

Am I trying to hard to create a classic domain model? Are there any "best practises" with regards to e.g. collections when using a component based engine? Is it more common to see denormalized data structures in component based engines?

I'm not sure if there's an established set of best practices, because even now there are a lot of different interpretations and implementations of the "component-based" model. In the interest of full disclosure, for a little over a year I was doing some very heavy database work as part of a project at work, and really grew to love relational data models and the separation of data and logic, so obviously this influenced what I believe to be one of the better implementations of a component-based design. In the case of collections, a collection isn't so much a literal object that contains other objects, as much as it is a result set of a particular query, namely one where you retrieve all objects with CollectionID = 'x' (or in our case, ArmyID = 'x'). The possible values of 'x', or rather the set of army ID's, can either be inferred from the distinct set of army ID's present across all UnitComponent's, or be stored on entities that contain an ArmyComponent. In the latter case you establish an informal constraint on army ID's, and the notion of "valid" versus "invalid" ID's, but whether or not you need that type of constraint is up to you. Usually you'd only have the ArmyComponent if an army needed additional information, and wasn't just a logical grouping or joining of units.

In this case, would building be an entity connected to a player via a PlayerBuildingComponent (or such)? I'm having difficulty actually separating entities and components at times, usually when relationships are involved (which I have quite many of).

Ideally, an entity is just a logical grouping of components, so there really isn't an entity "object" to add data to because it's a logical grouping, similar to the relationship between armies and units. It's all components. For player ownership, you'd have a PlayerOwnedComponent that can be put on any entity to indicate that it belongs to a particular player. For buildings, you would have a separate BuildingComponent that handles data just related to being a building. The rule of thumb is, if you have to ask whether or not a component needs to be separated into smaller components, it probably does It's a bit like the single responsibility principle, only when applied to data.

Concrete example of how it works in my game: Say a player has x farms. There is no interest for the player to see these farms as unique, so I would group them into some data structure which says: BuildingType: Farm, Amount: x. But then behaviour needs to be added to this entity (or component, depending on your answer to the above question), so we add ProducesFoodComponent to this entity. Am I on the right track with regards to making the Building an entity in this case, and then linking this entity building to my player entity via a PlayerBuilding Component on either the Player or Building entity? If I don't do separate the building data structure into an entity, I'll get components having children of components, which does not seem right.

This relates back to what I mentioned earlier about logical groupings and queries. You wouldn't have an actual data structure that groups farms, or even cares that they are farms. All the system cares about, is entities that have ProducesFoodComponents, and entites that belong to the player of interest (which will have a PlayerOwnedComponent of the correct player ID). Depending on your level of normalization, it will do a query not far off from this, to get the total food production amount for a player with ID 'x' (I apologize ahead of time for any syntax errors in my SQL!):

 select sum(food.food_amount) from produces_food_components as food inner join player_owned_components as player on food.entity_id = player.entity_id where player.owner_player_id = x

Now of course your implementation might not use an actual query language, but that's the essence of how systems would retrieve the information they need from the collection of components and relations.

2

##### Share on other sites

Am I trying to hard to create a classic domain model? Are there any "best practises" with regards to e.g. collections when using a component based engine? Is it more common to see denormalized data structures in component based engines?

I'm not sure if there's an established set of best practices, because even now there are a lot of different interpretations and implementations of the "component-based" model. In the interest of full disclosure, for a little over a year I was doing some very heavy database work as part of a project at work, and really grew to love relational data models and the separation of data and logic, so obviously this influenced what I believe to be one of the better implementations of a component-based design. In the case of collections, a collection isn't so much a literal object that contains other objects, as much as it is a result set of a particular query, namely one where you retrieve all objects with CollectionID = 'x' (or in our case, ArmyID = 'x'). The possible values of 'x', or rather the set of army ID's, can either be inferred from the distinct set of army ID's present across all UnitComponent's, or be stored on entities that contain an ArmyComponent. In the latter case you establish an informal constraint on army ID's, and the notion of "valid" versus "invalid" ID's, but whether or not you need that type of constraint is up to you. Usually you'd only have the ArmyComponent if an army needed additional information, and wasn't just a logical grouping or joining of units.

>In this case, would building be an entity connected to a player via a PlayerBuildingComponent (or such)? I'm having difficulty actually separating entities and components at times, usually when relationships are involved (which I have quite many of).

Ideally, an entity is just a logical grouping of components, so there really isn't an entity "object" to add data to because it's a logical grouping, similar to the relationship between armies and units. It's all components. For player ownership, you'd have a PlayerOwnedComponent that can be put on any entity to indicate that it belongs to a particular player. For buildings, you would have a separate BuildingComponent that handles data just related to being a building. The rule of thumb is, if you have to ask whether or not a component needs to be separated into smaller components, it probably does It's a bit like the single responsibility principle, only when applied to data.

Concrete example of how it works in my game: Say a player has x farms. There is no interest for the player to see these farms as unique, so I would group them into some data structure which says: BuildingType: Farm, Amount: x. But then behaviour needs to be added to this entity (or component, depending on your answer to the above question), so we add ProducesFoodComponent to this entity. Am I on the right track with regards to making the Building an entity in this case, and then linking this entity building to my player entity via a PlayerBuilding Component on either the Player or Building entity? If I don't do separate the building data structure into an entity, I'll get components having children of components, which does not seem right.

This relates back to what I mentioned earlier about logical groupings and queries. You wouldn't have an actual data structure that groups farms, or even cares that they are farms. All the system cares about, is entities that have ProducesFoodComponents, and entites that belong to the player of interest (which will have a PlayerOwnedComponent of the correct player ID). Depending on your level of normalization, it will do a query not far off from this, to get the total food production amount for a player with ID 'x' (I apologize ahead of time for any syntax errors in my SQL!):

 select sum(food.food_amount) from produces_food_components as food inner join player_owned_components as player on food.entity_id = player.entity_id where player.owner_player_id = x

Now of course your implementation might not use an actual query language, but that's the essence of how systems would retrieve the information they need from the collection of components and relations.

Thanks for the response, and sorry for not replying earlier; 10 month old baby to care of while at the same time trying to code when time allows. :)

I've decided to quote all you responded with, given that I'm now zooming in on what I need to do. Basically it sounds like classical database design, but where entities have been separated into a specific ID table, and where you then just add any data to this entity with the component tables.

So in essence any object which needs to have a uniqueness to it needs to be an identity?

A follow up question to this is that of templates. Given that someone will be creating template "classes" to decide from: The player can chose a race for example, which needs to be predefined. One way of doing this would be to have xml files which you then use to insert into the component model, or perhaps even have a component which classifies certain entities as templates. Any experience using templates with component engines?

0

##### Share on other sites

I've decided to quote all you responded with, given that I'm now zooming in on what I need to do. Basically it sounds like classical database design, but where entities have been separated into a specific ID table, and where you then just add any data to this entity with the component tables.

Ideally, yes, your entity "table" would only contain a single ID field, and each "row" in the component "tables" would reference an entity ID. An entity is then just the collection of all component "rows" with a particular entity ID. I put those terms in quotes because in all likelihood you wouldn't be using an actual database (i.e. MySQL, PostgreSQL, SQL Server, etc.), but rather something which implements a similar relational model.

So in essence any object which needs to have a uniqueness to it needs to be an identity?

Well, yes, the entity ID is unique, which by definition gives it identity... if I interpreted your statement correctly?

A follow up question to this is that of templates. Given that someone will be creating template "classes" to decide from: The player can chose a race for example, which needs to be predefined. One way of doing this would be to have xml files which you then use to insert into the component model, or perhaps even have a component which classifies certain entities as templates. Any experience using templates with component engines?

That's certainly one way of handling templates -- you create a template entity (commonly referred to as an 'archetype') from which you clone to create new entities.

There's also another approach based on the flyweight pattern where you can create two versions of each component "table", one which holds static shared data (max health, max speed, etc.) and one which holds dynamic individual data (current health, current speed, position, etc.). You then have two types of entities, your "type" entities which store shared data, and your "instance" entities would represent the actual objects in the game, and reference "type" entities for their shared data. It's analogous to the difference between a class' member data (per-instance), and it's static data (per-type). Essentially, you're just implementing static data in a relational model.

Lastly, there's a hybrid approach where you use archetypes, and each entity refers to the archetype from which is was cloned. Then, you allow each component field to be "nullable", where a "null" values indicates that the archetype value should be referenced instead of the entity in question's value. This should give you the best of both worlds in terms of memory and flexibility, since you can share data when it's identic to the archetype value and set it locally when it changes (akin to copy-on-write), at the cost of more complexity in the value set/get logic.

1

##### Share on other sites

I have a pretty good idea of how I'll manage my components and entities now.

Moving on there's the question of subsystems. I've been making some plans for how to structure the game in terms of components, and have come to the following question/thought: If a player constructs a building, this building is in a state known as construction, where the player does not gain full benefits of a fully built house. So in essence it's in a particular state for a while and then progressing to another once completed.

I suppose that much of the in-game logic of these things happen in subsystems?

Let's me try and model the previous question with how it would perhaps look with entities/components.

We have a player entity, and some components to represent that this player has a building in construction then moving on to become fully built. My way of modeling this would as follows:

One entity for the player. This entity would have a PlayerBuildingComponent connected to the entity below.

One entity for the building in construction. This would be marked as a building by having a BuildingComponent (With variables for name + total amount). It would also have a ConstructionComponent with amount of time left until completed. The building is not yet fully utilizing it's potential, so it can only house 100 people while being constructed, it thus has a PopulationCapacityComponent with amount set to 100.

Time passes on and the building becomes completed, but it should now house 200 people instead of 100. Is this the responsibility of the ConstructionSubSystem normally? I really don't want to move any logic to my components, so I'm keen on putting this kind of logic in the subsystem.

0

##### Share on other sites

One entity for the player. This entity would have a PlayerBuildingComponent connected to the entity below.

I wouldn't model the one-to-many relationship by having the "one" reference the "many" in this case, but rather the other way around. The player entity wouldn't directly store which buildings it owns -- in order to retrieve that information it has to perform a query with a join, along the lines of what I posted earlier. This also enables a much looser coupling between players and buildings, since the player entity doesn't have to updated at all whenever buildings are created and destroyed.

One entity for the building in construction. This would be marked as a building by having a BuildingComponent (With variables for name + total amount). It would also have a ConstructionComponent with amount of time left until completed. The building is not yet fully utilizing it's potential, so it can only house 100 people while being constructed, it thus has a PopulationCapacityComponent with amount set to 100.

The name of the building should probably go in a separate NameComponent, because it isn't something that's particular to it being a building (just about everything has a name). I'm not sure what you mean by "total amount", but if it has to do with construction then it should go in the ConstructionComponent. If it's building capacity, then yes that makes sense to keep in the BuildingComponent. Whether or not you need a separate component altogether for capacity, depends on whether or not other types of objects can hold people. If it's just buildings, then you don't need a separate component. How you split up these components will be very specific to the gameplay and at what granularity you want functionality to be customizable and interchangeable.

Time passes on and the building becomes completed, but it should now house 200 people instead of 100. Is this the responsibility of the ConstructionSubSystem normally? I really don't want to move any logic to my components, so I'm keen on putting this kind of logic in the subsystem.

If the capacity changes as a result of construction being completed, then yes your construction system would increase the capacity. If the capacity goes down because the building is run-down and ill-maintained, let's say, then the "run-down" system would change the capacity. The BuildingComponent could then store the various various capacities, or multipiers (however you want that to work), so the different systems know how the building (namely its capacity) should change in these circumstances.

1

##### Share on other sites

If the capacity changes as a result of construction being completed, then yes your construction system would increase the capacity. If the capacity goes down because the building is run-down and ill-maintained, let's say, then the "run-down" system would change the capacity. The BuildingComponent could then store the various various capacities, or multipiers (however you want that to work), so the different systems know how the building (namely its capacity) should change in these circumstances.

I'd be wary of having multiple systems modifying the same property of a Component. Instead, I would have one system that is responsible for setting the current population capacity based on various states (e.g. whether a building is in construction, how long has been since it was maintained, etc...).

Of course this doesn't necessarily mean you have a construction system, a run-down system (to track how long it's been since it was maintained), a population-setting system, etc.... They could all be different stages of the Update cycle of the same "building" system (assuming they all rely on the same set of components).

0

##### Share on other sites

One entity for the player. This entity would have a PlayerBuildingComponent connected to the entity below.

I wouldn't model the one-to-many relationship by having the "one" reference the "many" in this case, but rather the other way around. The player entity wouldn't directly store which buildings it owns -- in order to retrieve that information it has to perform a query with a join, along the lines of what I posted earlier. This also enables a much looser coupling between players and buildings, since the player entity doesn't have to updated at all whenever buildings are created and destroyed.

Ah yes ofcourse. Higher cohesion.

One entity for the building in construction. This would be marked as a building by having a BuildingComponent (With variables for name + total amount). It would also have a ConstructionComponent with amount of time left until completed. The building is not yet fully utilizing it's potential, so it can only house 100 people while being constructed, it thus has a PopulationCapacityComponent with amount set to 100.

The name of the building should probably go in a separate NameComponent, because it isn't something that's particular to it being a building (just about everything has a name). I'm not sure what you mean by "total amount", but if it has to do with construction then it should go in the ConstructionComponent. If it's building capacity, then yes that makes sense to keep in the BuildingComponent. Whether or not you need a separate component altogether for capacity, depends on whether or not other types of objects can hold people. If it's just buildings, then you don't need a separate component. How you split up these components will be very specific to the gameplay and at what granularity you want functionality to be customizable and interchangeable.

Total amount would be the number of buildings of type x contained in this entity. I don't want a separate row for each type x building, but instead group them into a column (total_amount) instead.

Here's the data (not necessarily defined as a whole component) contained for each building:

type/name of building, total number of buildings, state = {in construction, developed} , living capacity (varies depending on state), days until completed (> 0 if in construction)

There is one thing I forgot to mention. A player has Land which he/she constructs buildings on. Perhaps a more suitable model would simply be to have a LandComponent with aformentioned data, and if land has not been built then type/name would be set to "Land" and state to Unexploited or something similar?

Each building would also have bonuses that would take effect when the building is completed. Say a building increases attacking effect by x%, then some AttackSubSystem would need this information when a player attacks. But the building's bonus does not go into effect until it is completed. How does one model this state change best, while still maintaining high cohesion in the AttackSubSystem (not having to know too much about the building's logic)? I have two options here that spring to mind: 1) The AttackComponent has two columns, one for active value, and one for "desired/aim/target"-value. The subsystem always uses the active value, while the BuildingSubSystem copies target value to active value when the building is completed. 2) Another AttackModifierComponent is introduced: AttackModifiedInProgressComponent. This component would be connected to the building when first constructed and then later converted to an AttackModifierComponent.

Option 2 looks really ugly and adds complexity IMO. Any other options?

Time passes on and the building becomes completed, but it should now house 200 people instead of 100. Is this the responsibility of the ConstructionSubSystem normally? I really don't want to move any logic to my components, so I'm keen on putting this kind of logic in the subsystem.

If the capacity changes as a result of construction being completed, then yes your construction system would increase the capacity. If the capacity goes down because the building is run-down and ill-maintained, let's say, then the "run-down" system would change the capacity. The BuildingComponent could then store the various various capacities, or multipiers (however you want that to work), so the different systems know how the building (namely its capacity) should change in these circumstances.

I'm somewhat afraid of several subsystems acting on the same data, although in some cases I don't see any other way (common resources for example). Perhaps the multiplier suggestion would be possible during state change as well (read question/suggestion above with regards to in construction/developed)? When a building is in construction you would add a BonusMultiplier of 0.0 to the AttackModifier (if that building would have any such modifiers), and then change this to 1.0 once the building is completed.

Edited by phiwer
0

##### Share on other sites

If the capacity changes as a result of construction being completed, then yes your construction system would increase the capacity. If the capacity goes down because the building is run-down and ill-maintained, let's say, then the "run-down" system would change the capacity. The BuildingComponent could then store the various various capacities, or multipiers (however you want that to work), so the different systems know how the building (namely its capacity) should change in these circumstances.

I'd be wary of having multiple systems modifying the same property of a Component. Instead, I would have one system that is responsible for setting the current population capacity based on various states (e.g. whether a building is in construction, how long has been since it was maintained, etc...).

Of course this doesn't necessarily mean you have a construction system, a run-down system (to track how long it's been since it was maintained), a population-setting system, etc.... They could all be different stages of the Update cycle of the same "building" system (assuming they all rely on the same set of components).

In some cases I have difficulty seeing this fall through 100% though. Say you have a money component, then probably many systems would affect this component, or is there any way of handling this?

0

##### Share on other sites

Well, I'm assuming population capacity is something that can be expressed as an equation based on other variables. So there should only be one place in code that evaluates it.

You're right that money is different. Generally you would have one time events that subtract or add an amount to this - so there is no equation that gives you the current amount of money. So yes, my claim that multiple systems shouldn't modify the same property of a Component isn't correct. It really depends on what that property expresses. For something like Money, I might make that only accessible through methods (e.g. GetMoney(), AddMoney(), SubtractMoney()).

Each building would also have bonuses that would take effect when the building is completed. Say a building increases attacking effect by x%, then some AttackSubSystem would need this information when a player attacks. But the building's bonus does not go into effect until it is completed. How does one model this state change best, while still maintaining high cohesion in the AttackSubSystem (not having to know too much about the building's logic)? I have two options here that spring to mind: 1) The AttackComponent has two columns, one for active value, and one for "desired/aim/target"-value. The subsystem always uses the active value, while the BuildingSubSystem copies target value to active value when the building is completed. 2) Another AttackModifierComponent is introduced: AttackModifiedInProgressComponent. This component would be connected to the building when first constructed and then later converted to an AttackModifierComponent.

Option 2 looks really ugly and adds complexity IMO. Any other options?

Here are my thoughts:

So, AttackSystem needs to know the multiplier. But we don't want AttackSystem to know about buildings.

I think it's reasonable that there could be an AttackMultiplier component. When we want to figure out the overall attack multiplier, we enumerate all AttackMultipliers for entities associated with that player, and combine them together (the AttackSystem could do this once per cycle). AttackMultipliers don't need to be associated with buildings of course, they could be attached to any entity.

The question now becomes when does the AttackMultiplier component get added to buildings? Seems like the BuildingSystem code could have some logic that does this when construction is completed. Or better yet, buildings always have an AttackMultiplier component. The BuildingSystem (it's ok that the BuidlingSystem knows about AttackMultiplier - someone needs to) checks the current state of the building (constructed/rundown/etc) and assigns an appropriate value to AttackMultiplier (this could be 0% if the building isn't constructed, for instance).

The AttackMultiplier component could be generalized to BonusMultiplier component, and contain other types of bonuses. Then you might actually consider a BonusCalculationSystem that enumerates all the BonusMultiplier components each cycle, and adds them up for the final tally. Other systems would request this info from the BonusCalculationSystem.
0

##### Share on other sites

Well, I'm assuming population capacity is something that can be expressed as an equation based on other variables. So there should only be one place in code that evaluates it.

You're right that money is different. Generally you would have one time events that subtract or add an amount to this - so there is no equation that gives you the current amount of money. So yes, my claim that multiple systems shouldn't modify the same property of a Component isn't correct. It really depends on what that property expresses. For something like Money, I might make that only accessible through methods (e.g. GetMoney(), AddMoney(), SubtractMoney()).

Each building would also have bonuses that would take effect when the building is completed. Say a building increases attacking effect by x%, then some AttackSubSystem would need this information when a player attacks. But the building's bonus does not go into effect until it is completed. How does one model this state change best, while still maintaining high cohesion in the AttackSubSystem (not having to know too much about the building's logic)? I have two options here that spring to mind: 1) The AttackComponent has two columns, one for active value, and one for "desired/aim/target"-value. The subsystem always uses the active value, while the BuildingSubSystem copies target value to active value when the building is completed. 2) Another AttackModifierComponent is introduced: AttackModifiedInProgressComponent. This component would be connected to the building when first constructed and then later converted to an AttackModifierComponent.

Option 2 looks really ugly and adds complexity IMO. Any other options?

Here are my thoughts:

So, AttackSystem needs to know the multiplier. But we don't want AttackSystem to know about buildings.

I think it's reasonable that there could be an AttackMultiplier component. When we want to figure out the overall attack multiplier, we enumerate all AttackMultipliers for entities associated with that player, and combine them together (the AttackSystem could do this once per cycle). AttackMultipliers don't need to be associated with buildings of course, they could be attached to any entity.

The question now becomes when does the AttackMultiplier component get added to buildings? Seems like the BuildingSystem code could have some logic that does this when construction is completed. Or better yet, buildings always have an AttackMultiplier component. The BuildingSystem (it's ok that the BuidlingSystem knows about AttackMultiplier - someone needs to) checks the current state of the building (constructed/rundown/etc) and assigns an appropriate value to AttackMultiplier (this could be 0% if the building isn't constructed, for instance).

The AttackMultiplier component could be generalized to BonusMultiplier component, and contain other types of bonuses. Then you might actually consider a BonusCalculationSystem that enumerates all the BonusMultiplier components each cycle, and adds them up for the final tally. Other systems would request this info from the BonusCalculationSystem.

I think your last paragraph is the best option! If the building is not yet completed, then no bonus should exist at all. Representing them as 0:s in the model would add complexity when doing the actual calculations: Say you'd have a spell which would cancel a player's attack modifier, then you'd want a row in there where a zero actually meant "cancel all attacker modifiers", and then this would conflict with having a non-finished building's bonuses also represented by a zero.

I'd like some advice on naming my components as well. If a unit is able to be trained, is it prefable to name that component TrainableComponent, or CanBeTrainedComponent? Any pros cons with the naming scheme?

Edited by phiwer
0

##### Share on other sites

I'd be wary of having multiple systems modifying the same property of a Component. Instead, I would have one system that is responsible for setting the current population capacity based on various states (e.g. whether a building is in construction, how long has been since it was maintained, etc...).

Of course this doesn't necessarily mean you have a construction system, a run-down system (to track how long it's been since it was maintained), a population-setting system, etc.... They could all be different stages of the Update cycle of the same "building" system (assuming they all rely on the same set of components).

I wouldn't solve the issue of multiple systems modifying the same component value at the system design level, by only allowing one system access. One of the main reasons you completely isolate data and logic in this component design is to introduce a level of abstraction that allows the code structure to be independent from the data structure. However only letting one system modify a value couples the two structures together again and you lose the benefit of that abstraction.

Rather, I would solve the problem at the data level and use an approach that lets multiple systems modify a value in a well-defined way. You already touched upon such an approach with the various Modifier and Multiplier components. Generally speaking, you allow values to be backed by formulas, like x * A, (x + A) * B, etc., and allow systems to modify the inputs (A, B), whereas the constants (x) are sensible defaults or initial values. The formulas can have an arbitrary number of constants and inputs, and can vary per value depending on how you want systems to influence them. You don't necessarily have to implement such a system in the context of the component design, with individual components representing the various inputs and whatnot, since that seems as though it would get heavy with components for every input of every formula, and it's not really "game" code per se... however that's neither here nor there. The point is that systems aren't modifying raw values, but rather adjusting them in the context of modifiers/multipiers/bonues/etc., and you aren't gatekeeping them behind single systems. Best of both worlds.

Total amount would be the number of buildings of type x contained in this entity. I don't want a separate row for each type x building, but instead group them into a column (total_amount) instead.

An entity is a single building instance. What you're describing sounds like an entity to manage buildings, which could be the land entity (with a LandComponent) you mention later. However any given building instance wouldn't store the amount of its type. It would be redundant information on each building.

1

##### Share on other sites

I'd be wary of having multiple systems modifying the same property of a Component. Instead, I would have one system that is responsible for setting the current population capacity based on various states (e.g. whether a building is in construction, how long has been since it was maintained, etc...).

Of course this doesn't necessarily mean you have a construction system, a run-down system (to track how long it's been since it was maintained), a population-setting system, etc.... They could all be different stages of the Update cycle of the same "building" system (assuming they all rely on the same set of components).

I wouldn't solve the issue of multiple systems modifying the same component value at the system design level, by only allowing one system access. One of the main reasons you completely isolate data and logic in this component design is to introduce a level of abstraction that allows the code structure to be independent from the data structure. However only letting one system modify a value couples the two structures together again and you lose the benefit of that abstraction.

Rather, I would solve the problem at the data level and use an approach that lets multiple systems modify a value in a well-defined way. You already touched upon such an approach with the various Modifier and Multiplier components. Generally speaking, you allow values to be backed by formulas, like x * A, (x + A) * B, etc., and allow systems to modify the inputs (A, B), whereas the constants (x) are sensible defaults or initial values. The formulas can have an arbitrary number of constants and inputs, and can vary per value depending on how you want systems to influence them. You don't necessarily have to implement such a system in the context of the component design, with individual components representing the various inputs and whatnot, since that seems as though it would get heavy with components for every input of every formula, and it's not really "game" code per se... however that's neither here nor there. The point is that systems aren't modifying raw values, but rather adjusting them in the context of modifiers/multipiers/bonues/etc., and you aren't gatekeeping them behind single systems. Best of both worlds.

Should the systems be responsible for state logic (hard coded), or would this better be put into the data section of a component based system? One situation is when a LandComponent is not yet finished constructing a building. During this time the LandComponent should have a different set of attributes compared to when it's finished.

To me it seems as if there are two ways here:

1) Predefine/hard-code the known states of Land (Developed, Constructing, Empty), and then let the SubSystem shift values depending on current state.

2) Define states in the data, and let the LandComponentSystem implement a state machine.

Any other way of doing this? Comments regarding my two suggestions?

Total amount would be the number of buildings of type x contained in this entity. I don't want a separate row for each type x building, but instead group them into a column (total_amount) instead.

An entity is a single building instance. What you're describing sounds like an entity to manage buildings, which could be the land entity (with a LandComponent) you mention later. However any given building instance wouldn't store the amount of its type. It would be redundant information on each building.

Yes ofcourse. I forgot about the LandComponent when first posting, and like you say a building is an entity connected to a LandComponent.

0

##### Share on other sites

Should the systems be responsible for state logic (hard coded), or would this better be put into the data section of a component based system? One situation is when a LandComponent is not yet finished constructing a building. During this time the LandComponent should have a different set of attributes compared to when it's finished.

To me it seems as if there are two ways here:

1) Predefine/hard-code the known states of Land (Developed, Constructing, Empty), and then let the SubSystem shift values depending on current state.

2) Define states in the data, and let the LandComponentSystem implement a state machine.

Any other way of doing this? Comments regarding my two suggestions?

If any of the states confer some sort of special logic in the LandComponent that only applies to that particular state, then they'd have to be hard-coded somewhere in order for the component's code to act on that state (option 1). Otherwise you'd need to make the logic data-driven as well, i.e. a scripting system of some sort, but that's another subject altogether.

The exception is if the logic of each state follows some similar form that can be coded in a generic way, i.e. each state just corresponds to a population capacity modifier, and the logic to transition states isn't specific to the current state. Then the states can be purely data because they're not tightly coupled to state-specific logic, and you can write a single piece of logic that knows how to set the population capacity modifier and transition states (basically, option 2).

0

##### Share on other sites

Should the systems be responsible for state logic (hard coded), or would this better be put into the data section of a component based system? One situation is when a LandComponent is not yet finished constructing a building. During this time the LandComponent should have a different set of attributes compared to when it's finished.

To me it seems as if there are two ways here:

1) Predefine/hard-code the known states of Land (Developed, Constructing, Empty), and then let the SubSystem shift values depending on current state.

2) Define states in the data, and let the LandComponentSystem implement a state machine.

Any other way of doing this? Comments regarding my two suggestions?

If any of the states confer some sort of special logic in the LandComponent that only applies to that particular state, then they'd have to be hard-coded somewhere in order for the component's code to act on that state (option 1). Otherwise you'd need to make the logic data-driven as well, i.e. a scripting system of some sort, but that's another subject altogether.

The exception is if the logic of each state follows some similar form that can be coded in a generic way, i.e. each state just corresponds to a population capacity modifier, and the logic to transition states isn't specific to the current state. Then the states can be purely data because they're not tightly coupled to state-specific logic, and you can write a single piece of logic that knows how to set the population capacity modifier and transition states (basically, option 2).

True! I'll have to do futher analysis of this. As a first resort I think I'll go with option 1.

I've now started developing the component engine, and one question has come up. Although I don't want to do premature optimization I feel it's worthy of mentioning. I currently have a component called ChildEntityComponent, which is attached to entities that are children of some entity (e.g. Player has a lot of land). I've also developed a SubSystem for this component which many other subsystems will use, and as such it's important that it does fast lookup.

Some of the functions on this subsystem include: IsRoot, GetChildren, GetSiblings, GetParentEntity, GetRootEntity.

Right now there is only one way of traversing the relationship between entities (child to parent), so the GetChildren operation is expensive.

Does anyone have any good ideas for fast lookup of these operations? One idea I have is to let the ChildEntitySubSystem listen on events from the ChildEntityComponents and update a data structure for fast lookup for entities connected to one another. This encapsulates the knowledge of relationships between entities to the subsystem while still maintaining the overall component design (of parents not knowing directly about their children).

Any other suggestions?

0

##### Share on other sites

I've got a Children component that can be attached to an entity, and which contains a list of the child entities' ids.

In addition, each entity has an owner id. This isn't in a component, it's actually part of the Entity itself.

So the parent-child relationship is expressed in both directions. There is a system that takes care of keeping these in sync. Basically all add/remove requests go through the system.

I'd be interested to hear how others solve this.

0

##### Share on other sites

I've got a Children component that can be attached to an entity, and which contains a list of the child entities' ids.

What persistence mechanism do you use when saving this component with lists of entities? NoSQL?

In addition, each entity has an owner id. This isn't in a component, it's actually part of the Entity itself.

So the parent-child relationship is expressed in both directions. There is a system that takes care of keeping these in sync. Basically all add/remove requests go through the system.

I'd be interested to hear how others solve this.

Hmm. Given that you have the parent/owner on the entity itself, why not store the children there too?

0

##### Share on other sites

What persistence mechanism do you use when saving this component with lists of entities? NoSQL?

Each Component type knows how to serialize itself to/from a stream. So it just stores the number of children, and then their persistent ids.

Hmm. Given that you have the parent/owner on the entity itself, why not store the children there too?

Good question. The reason is that every entity has an owner, but very few have children.

Also, I was simplifying above - there are actually different classes of children. An entity can have transform children (such as a fire particle system attached to an entity for the torch model) or inventory children (that torch is now owned by the player, say). I re-use the same ownerId in either case. I'm not saying this is a good system (my framework is still very much a work in progress). In fact, it seems kind of flawed since an entity then can't be a member of both groups (although that never happens anyway in my scenarios).

I also should explain "every entity has an owner". I actually partition my id-space into two regions. One is for entities, and one is for top level "regions" of the game. So "top-level" entities are actually owned by a particular region. This is to support an open world, where regions (and all their child entities) are dehydrated and re-hydrated as the player moves about the world. (I could probably model this as a region entity that acts as an owner though, rather than artificially partitioning my id-space).

Anyway, I wonder if it would be useful to try to formalize a general group ownership mechanism. What type of ownership is there? Ones I can think of:

- An entity can be owned by a region of the world (let's call this a "persistence group")

- An entity can be attached physically to another (transform)

- An entity can belong to a player entity (e.g. this building belongs to 'x')

- An entity can be in a player's inventory

- ???

0

##### Share on other sites

I would argue you shouldn't have a ChildrenComponent, rather, the components that make it logical for an entity to have children should store the children in that component.

For example, a Car entity could have a CarComponent, and part of it's data is a list of entities riding in it.

An Army entity would have an Army component, and it would have the list of solider entities in the Army.

At least, that's how I'd do it.

Will

0

##### Share on other sites

I'm not sure if there's much benefit in having a general-purpose ChildComponent. As phil_t pointed out, there are a number of different types of parent-child relationships, and it's difficult to find a generalization of the logic and data required for each without dealing in the specifics of any particular type of relationship. If you do go down that route, I'd say you could store a parent ID at most, and then have utility methods to perform the typical get-children, get-siblings, get-parent, etc. operations. However anything beyond that and it would seem as though you're dealing in the particulars, i.e. does the parent "own" the children? Are they attached in a hierarchy? Are the children contained within the parent?

What you can probably do in lieu of having a special ChildComponent is create IChild and IParent interfaces that are implemented by the various components that need to use these relationships. Then you can build a set of utility methods (possibly a full system) that deals in these interfaces alone. Each component that implements these interfaces can do so in such a way that makes the most sense for that type of relationship, and they can have their own systems that augment the general-purpose interface with specific methods that make sense for their relationship.

0

##### Share on other sites

Let's take the case of gold as a component. Say you have a world of entities, and these entities in turn have some components which contain lists of entities.

To make this concrete (although a bit contrived):

World Entity (has WorldComponent)

WorldComponent in turn contains a list of Village Entities (has VillageComponent).

WorldComponent also has a list of Player Entities (has PlayComponent) that are out roaming the world but are not in villages.

VillageComponent also contains a list of Players, but these are specifically in villages.

There is also a GoldComponent, which each player has. Each village also has a GoldComponent (which the players can rob or such).

Now say I have a GoldSubsystem and there is a function GetTotalGold, which is suppose to compute all the gold for a specific entity and its children. So if I input a village I get all the gold in the village + all the gold of all the players. Nothing is static here, so sometime in the future I may decide to remove the GoldComponent from the village, but then I should still get the total gold of all the players in the village.

In this design, there must be some way of iterating through entities that are contained within components, and to query these if they contain specific components. This suggests that there should be an interface on the components to support this behaviour. Or am I modeling this wrong?

0

##### Share on other sites

Let's take the case of gold as a component. Say you have a world of entities, and these entities in turn have some components which contain lists of entities.

To make this concrete (although a bit contrived):

World Entity (has WorldComponent)

WorldComponent in turn contains a list of Village Entities (has VillageComponent).

WorldComponent also has a list of Player Entities (has PlayComponent) that are out roaming the world but are not in villages.

VillageComponent also contains a list of Players, but these are specifically in villages.

There is also a GoldComponent, which each player has. Each village also has a GoldComponent (which the players can rob or such).

Now say I have a GoldSubsystem and there is a function GetTotalGold, which is suppose to compute all the gold for a specific entity and its children. So if I input a village I get all the gold in the village + all the gold of all the players. Nothing is static here, so sometime in the future I may decide to remove the GoldComponent from the village, but then I should still get the total gold of all the players in the village.

In this design, there must be some way of iterating through entities that are contained within components, and to query these if they contain specific components. This suggests that there should be an interface on the components to support this behaviour. Or am I modeling this wrong?

Maybe there's a pure way around this, but, for simplistic purposes, wouldn't you have the ability to query an entity to see if it contains a certain type of component?  And then be able to process that specific component from that specific entity?  I would think you'd have to if you wanted to do something like what you suggest.

0

##### Share on other sites

Just to clarify, components shouldn't "contain" entities in the traditional sense. All the entities in the game should exist together in a flat structure, and the components should only store IDs to entities (there was also a recent article series on decoupling that covered this subject in particular).

Now say I have a GoldSubsystem and there is a function GetTotalGold, which is suppose to compute all the gold for a specific entity and its children. So if I input a village I get all the gold in the village + all the gold of all the players. Nothing is static here, so sometime in the future I may decide to remove the GoldComponent from the village, but then I should still get the total gold of all the players in the village.

In this design, there must be some way of iterating through entities that are contained within components, and to query these if they contain specific components. This suggests that there should be an interface on the components to support this behaviour. Or am I modeling this wrong?

You have the right idea, we just need to have the interfaces in the right place.

For this example, you can have the WorldComponent implement the IParent interface (it can be the parent of both villages and players), the VillageComponent implement both the IParent and IChild interfaces (it can be both the child of the world and a parent of players), and the PlayerComponent implement the IChild interface (it can be the child of both the world and villages).

You then create a ParentChildSystem which acts only on the components that implement these interfaces. Given a root object (such as the world or a village), you find all components on that entity which implement IParent. At the point, you then find all components across all entities that implement IChild, and reference any of the root object's IParent IDs. You then find all the IParent's on this new set of entities, and the IChild's on other entities that reference them, etc. It's basically a breadth-first search. Once you have the list of entities, the GoldSystem can find all the GoldComponents and tally them up, without concerning itself with parent/child relationships or hierarchy (since that's the ParenChildSystem's job).

The biggest downside here is that the generalized interfaces, combined with a lack of forward references from parent to child, can lead to objects being included that you didn't want, and rather inefficient searches (note the "all components across all entities" part of the search). The best way to fix this is to simply add the child IDs directly to the IParent component, and have the system keep the IParent and the IChild components in sync, as phil_t mentioned a few posts ago. It's still a BFS, except now you're not doing searches across all entities and components. This doesn't necessarily fix the pruning problem, where objects you don't want are returned in the search. As previously mentioned, there are different types of parent/child relationships, and you might only care about specific ones when doing certain searches. For instance, when counting gold, you probably don't want to consider objects that are just physically attached to the player or village, but perhaps objects that are actually "owned" by them. In that case, the interfaces can also expose what kind of relationship they are, and the search can prune them based on that.

If you want, you can also dispense with the interfaces altogether and have the GoldSystem know precisely which component types (i.e. WorldComponent, VillageComponent, PlayerComponent) it needs to query, as well as their exact relationships. For a small game this is the easiest approach, except you might find that some code gets duplicated as multiple systems end up querying the same parent/child hierarchies, since there is no interface type upon which to build a generalized solution.

Edited by Zipster
0

## Create an account

Register a new account