Sign in to follow this  
l0k0

Unity Component Entity Model Without RTTI

Recommended Posts

NetGnome    773
The best example of an ECS Framework is by the folks who made the Artemis framework ([url="http://gamadu.com/artemis/"]http://gamadu.com/artemis/[/url]). They even have a couple of example games that use the framework so you can start seeing how to put things together. T-Machine.org lays-out the concept of an ECS framework fairly well giving tips on what to-do and what not to do and generally how to go about using a ECS framework. I also believe there are some articles out there from the dungeon seige II devs that "pioneered" some of the concepts.

I'm currently converting and modifying aspects of the Artemis framework for c# to suit my own needs and extend capability (like support for more than 32/64 systems / component types) and quicker type mapping (eliminating hash lookups via static type variables)

Share this post


Link to post
Share on other sites
ZachBethel    921
Things are slowly becoming less blurry. Thanks for the Artemis link Net Gnome!

@SwiftCoder

So what you're getting at is having a fully generic entity type, but attach behavior and controller decorators to it? Do you have any sample code that demonstrates this technique (or a reference to a paper describing it?) I'm intrigued.

Here's basically how I understand the system to work:

A base entity is essentially an id. Components for this entity can be created and added to the world (which in turn delegates them to the appropriate component manager). The user can choose to create an actor class which basically holds the entity id and whatever explicit references to the components it needs to function. That actor then implements the game logic. This allows the actor itself to have weak links to its components, so we don't just create components and then let them drift off into the void, nor do we need to resort to a GetComponentOfType(...) function call. We eliminate this because an entity can have multiples of a given component. Additionally, components are coupled as they need (like Hodgeman pointed out).

Furthermore, the factory method itself might spawn several actors, such as a set of wheels for a car, along with the joints connecting them. The vehicle actor will want a reference to the joints, its health, etc. Additionally, the vehicle will connect several transform components to itself that delimit where the joints will connect. The factory function is then responsible for creating the set of entities and coupling them together as they need it. Thus, the vehicle actor knows nothing about the wheels unless it needs to (which it probably would if it wants to apply forces to them, etc), or the joints for that matter.

*sigh* This stuff is hard.

Share this post


Link to post
Share on other sites
crancran    504
[quote name='ZBethel' timestamp='1326384280' post='4902031']So what you're getting at is having a fully generic entity type, but attach behavior and controller decorators to it? Do you have any sample code that demonstrates this technique (or a reference to a paper describing it?) I'm intrigued.
[/quote]

Your code you posted on the previous page was close to what Swift was describing but instead of deriving a class from Entity; you simply leave Entity as the final class. The entity class serves as a means to hold control information about the entity such as a unique ID, possibly a name/tag, and the list of components and behavior that give that entity instance it's unique traits and functionality.

The aim with ECS frameworks is about being data-driven. We can extract the pieces needed to construct a car entity and the instance values used by car entities from code. A lot of games do this by having a file that describes the template used to construct an entity by name/type and then another file that describes instance specific values based on an entity name/type. This "file" could also be a factory class if you want this managed inside your code or even a SQL database when we consider online games, but the goal here is that the data-aspect of an entity is completely isolated

I chose to use XML files for my first pass implementation. I have a template XML file that describes all components needed to create my entities, which provides similar functionality to your Create() method on your Car class. The second XML file is for instance specific values that describe data such as location, min/max velocity of my entity, scale of the model, etc. This way if I want to mass produce 500 entities of a car I could easily do so by having my entity factory load my template of a car entity once and then clone it the number of times needed. Afterward it is a simple setting of instance specific properties.

But at the core, you have 1 entity class that is generic and you allow the data to drive the aspects contained within.

HTH

Share this post


Link to post
Share on other sites
BeerNutts    4400
[quote name='ZBethel' timestamp='1326384280' post='4902031']
Things are slowly becoming less blurry. Thanks for the Artemis link Net Gnome!

@SwiftCoder

So what you're getting at is having a fully generic entity type, but attach behavior and controller decorators to it? Do you have any sample code that demonstrates this technique (or a reference to a paper describing it?) I'm intrigued.

Here's basically how I understand the system to work:

A base entity is essentially an id. Components for this entity can be created and added to the world (which in turn delegates them to the appropriate component manager). The user can choose to create an actor class which basically holds the entity id and whatever explicit references to the components it needs to function. That actor then implements the game logic. This allows the actor itself to have weak links to its components, so we don't just create components and then let them drift off into the void, nor do we need to resort to a GetComponentOfType(...) function call. We eliminate this because an entity can have multiples of a given component. Additionally, components are coupled as they need (like Hodgeman pointed out).

Furthermore, the factory method itself might spawn several actors, such as a set of wheels for a car, along with the joints connecting them. The vehicle actor will want a reference to the joints, its health, etc. Additionally, the vehicle will connect several transform components to itself that delimit where the joints will connect. The factory function is then responsible for creating the set of entities and coupling them together as they need it. Thus, the vehicle actor knows nothing about the wheels unless it needs to (which it probably would if it wants to apply forces to them, etc), or the joints for that matter.

*sigh* This stuff is hard.
[/quote]

ZBethel,

My dev journal (see my sig) has 4 parts covering my Component Based Entity System for a particular game I had previously created using plan OOP. It's a system where the components have both data and logic, and all information is passed between components and Entities via Events.

It is flawed, no doubt, as it was my 1st attempt at such a system, but maybe it will give you one other avenue to get ideas.

Good Luck

Share this post


Link to post
Share on other sites
NetGnome    773
The best way i've found to think of ECS Frameworks is to think of them like a database.

Components are Rows in a Table (Component Types), Entities are Primary Keys, and Systems are mechanisms that operate (Create, Read, Update, Delete) on one to many tables (component types) based on their current Primary Key (Entity) of interest.

Treat Entities like a unique ID (literally just an ID container, and nothing more). They shouldnt track anything, let an Entity Management class do that. Entities can literally be as simple as a bit array with their id being their index with true being active and false representing deactivated/unactivated entities. Although i prefer a very lightweight class with just an int for ID (allows me to map to component arrays to quickly establish ownership of a component in the array {it owns the component at the ID's index}). Components should strictly be data containers and nothing more (avoid observer patterns if you can, let a manager take care of that during an update cycle), and let Systems do all the work and communications. These simple concepts will help you do well, and keep things decoupled which will give you TONS of flexibility and allow for easier expansion as you add more features.

Granularity in your components is important. They should describe enough to get the job done, but not more than is required. Don't make them monolithic and dont make them microscopic. This prevents you from having too many specialized systems or too many component retreivals. If you find you use your Velocity component always with a positional component, perhaps you should merge them into a movement or spatial component. Instead of components for each joint in a model, perhaps just have a skeleton component that encompases all the joints required. Don't have a "player" component, just tag an entity as "the player" and build it as you would any other entity.

Finally, when you write your systems, try to keep them as generic as possible. A missile system shouldn't care if its a player or a monster shooting something, only that you have an emission point, a projectile, and a direction. This keeps specialization down and allows you to construct entities alot easier. Systems can be active (execute every update cycle), Passive (execute when called by another system or event), Semi-active (delayed or intermittent), etc. so don't think they all have to behave the same either.

Anyway, hope that helps

Share this post


Link to post
Share on other sites
ZachBethel    921
[quote name='Net Gnome' timestamp='1326394484' post='4902069']
The best way i've found to think of ECS Frameworks is to think of them like a database.

Components are Rows in a Table (Component Types), Entities are Primary Keys, and Systems are mechanisms that operate (Create, Read, Update, Delete) on one to many tables (component types) based on their current Primary Key (Entity) of interest.

Treat Entities like a unique ID (literally just an ID container, and nothing more). They shouldnt track anything, let an Entity Management class do that. Entities can literally be as simple as a bit array with their id being their index with true being active and false representing deactivated/unactivated entities. Although i prefer a very lightweight class with just an int for ID (allows me to map to component arrays to quickly establish ownership of a component in the array {it owns the component at the ID's index}). Components should strictly be data containers and nothing more (avoid observer patterns if you can, let a manager take care of that during an update cycle), and let Systems do all the work and communications. These simple concepts will help you do well, and keep things decoupled which will give you TONS of flexibility and allow for easier expansion as you add more features.

Granularity in your components is important. They should describe enough to get the job done, but not more than is required. Don't make them monolithic and dont make them microscopic. This prevents you from having too many specialized systems or too many component retreivals. If you find you use your Velocity component always with a positional component, perhaps you should merge them into a movement or spatial component. Instead of components for each joint in a model, perhaps just have a skeleton component that encompases all the joints required. Don't have a "player" component, just tag an entity as "the player" and build it as you would any other entity.

Finally, when you write your systems, try to keep them as generic as possible. A missile system shouldn't care if its a player or a monster shooting something, only that you have an emission point, a projectile, and a direction. This keeps specialization down and allows you to construct entities alot easier. Systems can be active (execute every update cycle), Passive (execute when called by another system or event), Semi-active (delayed or intermittent), etc. so don't think they all have to behave the same either.

Anyway, hope that helps
[/quote]

Fascinating. I never thought about it like that, but it makes sense. Once again (sorry), I have a couple questions. Organizing the data like that is easy enough, and delegating each component type to its own manager is easy enough as well. The part that I'm still a little confused about is where the overall entity logic should be. For instance, if your player is just another entity, and its components are spread out among all these independent systems, how do you collaborate when them in order to build game logic? I'd imagine you have some sort of player controller that handles input and such, but you also need logic to handle things like whether the player is dead yet, if he can throw a grenade or not, whether he's invincible, etc. How would your system wrap things up neatly into a usable higher level entity (i.e. an object that holds the entity primary key + whatever component keys it needs).

This becomes difficult once you require a completely data driven architecture, because you can't just create a player class that holds the primary key of the entity and links to its components. Either you're going to need to be able to query the entity manager for specific components (which gets back to Hodgeman's point about requiring one of everything), or point components at each other. If we think about the entity as data, and the systems themselves as logic, it's hard for me to wrap my mind around how this would work in real life--because the logic is so fragmented among systems.

I really like your idea of an xml template/instance architecture. Is that something you developed for a hobby project? Do you have some source code samples you could share? Or maybe a sample xml file? It sounds really neat.

Thanks for taking the time to answer my questions. I wish I could meet one of you guys in person and talk about it over a white board. It's tough communicating stuff like this over text sometimes.

[b]*edit* [/b]I've been some blogs, and I came across this excerpt on piemaster.net about the Artemis framework:

[indent=1]The logic is instead encapsulated in the [b]Systems [/b]that accompany the entities and components. A ‘System’ is simply an object that reads and updates the data in any relevant components. You could say it’s simply the update function of the relevant components refactored into its own object.[/indent]

[indent=1]I say “relevant components” because of how the systems do their processing. Instead of the game iterating imperatively through all of the entities and updating each in turn, the systems take more of a functional programming approach. Each system specifies a set of components that it’s interested in, and then in each frame it processes only those entities that contain all specified components.[/indent]

[indent=1]Furthermore, each system exists to perform a specific role, updating all instances of the relevant components before passing control to the next system. You could say that the components are processed in cross-sections across all entities at once, rather than entities (and all of their child components) being processed in chunks.[/indent]

So somehow, the systems themselves compose the game logic, and when they so require, they can bring in various components with certain qualities.

Share this post


Link to post
Share on other sites
swiftcoder    18426
[quote name='ZBethel' timestamp='1326464193' post='4902345']
The part that I'm still a little confused about is where the overall entity logic should be. For instance, if your player is just another entity, and its components are spread out among all these independent systems, how do you collaborate when them in order to build game logic? I'd imagine you have some sort of player controller that handles input and such, but you also need logic to handle things like whether the player is dead yet, if he can throw a grenade or not, whether he's invincible, etc.

How would your system wrap things up neatly into a usable higher level entity (i.e. an object that holds the entity primary key + whatever component keys it needs).[/quote]
You wouldn't necessarily wrap that all up into a single class - the very phrase 'overall entity logic' is misleading, overall logic is dictated by the interactions of components/subsystems. And we can take this much, much further...

For the sake of clarity, let's define what components/subsystems are used to implement a typical player class:[list]
[*]Transform - this component the character's position/orientation
[*]FPSInput - this class processes mouse/keyboard input to move the player (and forward some keys to other systems
[*]CollisionPrimitive - this component provides a collision hull, so the Physics subsystem can respond to collisions
[*]Inventory - this component receives 'SwitchWeapon' events from the FPSInput, and does so if legal
[*]Weapon (primary and secondary) - these components receive 'FireWeapon' events from FPSInput, and do so if legal (has ammo, fire rate)
[*]Health - this component tracks damage to the player, and destroys *all* the components when health hits zero
[/list]
Here's a rough dependency diagram, illustrating what components are connected to each other:

[img]http://i.imgur.com/YlWYk.png[/img]

See anything missing? That's right, the 'Entity'. And that's because the entity doesn't actually do anything in this system - absolutely all behaviour is handled by the components.

Now obviously this is a simple case, and things aren't always so rosy in the real world, but in general it's possible to eliminate the whole 'entity' concept entirely, and build a pure 'Component System' instead...

*Edit: one does usually keep the Entity concept around as a tag, however. Otherwise it's quite hard to programatically delete an entity, or perform a number of other entity-related tasks.

Share this post


Link to post
Share on other sites
NetGnome    773
From what i usually see, is you have a series of systems that concern themselves with the player's entity. This means there is an entity ID out there, that you've remembered in some way, that represents the player. You dont extend the Entity class with a PlayerEntity class, you just remember that Entity 123 is the player. I like how Artemis does it and keeps a dictionary of notable single entities (i.e., mapping the string "PLAYER" or const PLAYER to Entity 123) through a Tag Manager (you could probably modify this to be faster with pre-defined static types as well). or important groups through a Group Manager. Each system knows which entities it cares about and then uses thier IDs as indexes through component mappers.

Anyway, back to your question. The basic importance is that Entities are IDs, Components are just data containers, and systems crunch through components based on some entity ID. Systems do anything you want game logic to do. Obviously, you're going to have player focused systems, which crunch on components owned by the entity tagged PLAYER. But, you may even want to think of it more abstractly. Perhaps you dont need to be so focused on the PLAYER, but perhaps a specific type of key component of interest, like Controllable. Perhaps you only have one Controllable component in the entire game space (or perhaps several for a squad based game), and you move it (i.e., re-assign it or re-create it) around to various entities along with a Camera Focus component. The system just takes keyboard inputs and then uses those to modify the Spatial component of the entity that owns the Controllable component

Once you start thinking about it, you're not really controlling the model being rendered, but you're really just affecting position data points which are tied to this entity, which in turn are being represented by something on the screen from some arbitrary viewpoint by the rendering system. The rendering system doesnt care that its the player, only that it should put texture x or model y at coordinate z and render from viewpoint v. You could do some really crazy things when you string components together and add/remove them. Like an item that grants an effect that then morphs into an enemy that you fight then becomes a corpse quest item that you pick up that can be used in a recipe to make some other item which you turn in for a reward. Without an ECS Framework, making that happen would be an absolute nightmare, but you could do it in an ECS Framework by just dynamically adding/removing/updating components to an entity.

Its really a different way to think about things. It shows how things we think are related to eachother really have absolutely nothing to do with eachother, since our human need to categorize/group unrelated things gets in the way.

I will not lie, ECS Frameworks have data overhead to them, and therefore may not suit everyones needs (i.e., may be overkill). They can be fast (6000+ created, rendered, destroyed entiteis per second / 1,000,000+ created, unrendered, destroyed entities per second) [i believe this is what artemis touts], but only if you put some good thought into their management. They are great for games with complex systems (RPGs, roguelikes, MMOs particularly), since you can separate logic easier and you have significantly less ripple effects when you modify systems.

Share this post


Link to post
Share on other sites
ZachBethel    921
Wow, you guys are awesome. Thanks for your detailed replies. Things are clicking in my head! :) I'm going to work out some architectural diagrams to make sure I've got this figured out. I may have a couple more questions later.

Share this post


Link to post
Share on other sites
ZachBethel    921
How then do we handle hierarchies of entities? Back to my notorious car example, the car mesh itself will have wheels, but the physics component needs to have articulate joints and bodies set up for different parts of the car. If the car explodes or loses a wheel, that wheel needs to become an independent entity. I guess my question is, am I better off modeling a physics/mesh component as a single fundamental primitive (joint, mesh, rigid body, etc), or having some generic physics component that describes articulate joints/bodies. It seems like the former is a better option. It allows a wheel to stay independent from the car, but the wheel is still "owned" by the car, i.e. it needs to be controlled by the vehicle logic.

I guess I could have some sort of vehicle component that specifies which joints/entities are used by the wheels, and then a vehicle system that controls how that articulate figure interacts, but it doesn't seem clear to me. These systems model nicely when an object is a primitive. When it's a complex object composed of other entities, it seems to break down. I know that it highly depends on the requirements of the game, but I'm just trying to think through possible scenarios of what could happen, and then how it could be solved.

In my case, I want to model a tank with articulate pieces (like wheels, a base, the turret, and the barrel itself). They'll be represented using independent rigid bodies/meshes for each part of the tank. If I make the tank one big entity, then I'll need to have the physics and rendering components support multiple meshes and rigid bodies, along with the joints to hold them all together. Benefits of this approach are that the entity is kept contained, and the physics/mesh components can be built to support multiple primitives. The immediate con is that individual components are not independent. So, say, if you wanted your turret to have its own health component, you can't really do that. You'd have to build a special VehicleHealth component that holds all of the health values for your entity's parts. The same could go for a skinned mesh. When a player dies, you might want body parts to go flying everywhere. Additionally, if for some reason you want your object to split into multiple distinct objects, that becomes difficult. Do you model those parts as one whole entity with components built to support multiple primitives? Or do you build an entity as a primitive object that can have child entities attached to it? There are so many options, and I don't really have the experience to know which is best in reality.

Any thoughts?

Share this post


Link to post
Share on other sites
swiftcoder    18426
Ok, so we have three types of entity here: a [b]Vehicle[/b], a [b]Chassis[/b] and some [b]Wheel[/b]s. The [b]Chassis[/b] and the [b]Wheel[/b]s each have a [b]Transform[/b], a [b]CollisionComponent[/b] (probably a convex hull for chassis, sphere for wheels), and a [b]VisualRepresentation[/b] (i.e. the model to render). The [b]Vehicle[/b] has a set of [b]Joint[/b]s, which are attached to the [b]Chassis[/b] on one end, and the [b]Wheel[/b] on the other.

Now: as far as the Graphics sub-system is concerned, there are 5 [b]VisualRepresentation[/b]s. As far as the Physics sub-system is concerned, there are 5 [b]CollisionComponent[/b]s, connected together by 4 [b]Joint[/b]s. As far as the AI sub-system is concerned, there is a single [b]Vehicle[/b] entity.

What happens when the Vehicle is destroyed? Well, the [b]Joint[/b]s are components of the [b]Vehicle[/b], so they are destroyed too. And since the [b]Chassis[/b] and the [b]Wheel[/b]s have been independent entities from the start, they go on rendering, simulating, and colliding, just like always... Problem solved.

Share this post


Link to post
Share on other sites
NetGnome    773
Here is a short example showing performance of the ECS Framework i've been working on.

You can find it here: [url="https://github.com/netgnome/ECSFramework-Example"]https://github.com/n...amework-Example[/url]
Framework here: [url="https://github.com/netgnome/ECSFramework"]https://github.com/n...me/ECSFramework[/url]

note: this is a modified version of the Artemis framework to run under c# with other improvements of my own. it is currently incomplete and thus far will only reliably run the given demo. currently this is given as example only, when and if it matures, I'll likely apply the BSD license to it (to follow Artemis' guidelines).

At present, it will run the given demo creating and rendering 20,000 texture entities and jitter-translate them @ 80+ fps (though my rig is fairly beefy). If performance remains linear (which it should since updates are done linearly O(n)), it should be able to run 40,000 at 40+ fps. If/when i implement a parallel entity system processor, i may be able to get it to O(log(n)).

EDIT: realized i was running SWTOR in the background, so i decided to re-run my test with it off at 20k entities... got about 80+ fps (w/ swotor it was 10,000 @ 60+fps)

EDIT2: whoops, just realized i was running in debug mode... *slaps forehead*... it'll run 40k @ 95+fps... (thats release.exe +compiler optimize).

Share this post


Link to post
Share on other sites
DjMaSh    198
I love this type of stuff. this thread has been an interesting read.There has been a lot of talk about typical things that you would class as game objects such as monsters, rockets, and vehicles. But what about UI? Do you guys create UI systems to manage your user interfaces? and then have ui components like buttons, sliders, images etc? i like this idea, then you could attach text above the player easily, or have destructible in game ui's throughout your world, as well as easily integrating your HUD with events from your player entity. You could even create an entity that has a button and physics component, giving you a button that you can both click on, and also kick and throw around your world.

:o

Share this post


Link to post
Share on other sites
NetGnome    773
The examples i've come accross mostly have a special system for the UI element, so you literally can attach it anywhere. But, with some clever inginuity, perhaps merging concepts of ECS and OO, you could use components as reference containers which your UI system then uses to issue draw/update commands to.

Basically the component would literally be something generic like UI Component, but it would have a data reference pointing to an object that implements interface IUserInterface of some type which inheritors implement draw/update/whatever methods. This way the system doesn't need to care what its running, nor does the component care what it carries other than its a IUserInterface of some type. I guess when you instantiated the component you would do something like (using my ECSFramework as an example)

[CODE]
ecsInstance.EntityManager.addComponent(entity, new UIComponent(new HealthBar()));
[/CODE]

the systems would implement something like this:

[CODE]
//for a UI updating system:
protected override void process(Entity entity)
{
UIComponent ui = (UIComponent) uiMapper.get(entity);
ui.IUserInterface.update(entity);
}

//for a UI rendering system:
protected override void process(Entity entity)
{
UIComponent ui = (UIComponent) uiMapper.get(entity);
ui.IUserInterface.draw(entity);
}
[/CODE]

and HealthBar would look something like this

[CODE]
public class HealthBar : IUserInterface
{
public void update(Entity entity)
{
//do update stuff here
}

public void draw(Entity entity)
{
//do draw stuff here
}
}
[/CODE]


I could see this used for alot of other scenarios as well.

EDIT: updated examples so they made sense with my text blurb

Share this post


Link to post
Share on other sites
Antheus    2409
[quote]omething generic like UI Component[/quote]

Which is RTTI. It can also be expressed differently, such as passing function pointers or delegates or using a switch. Different name, same thing.

No RTTI would be something like this:[code]int health[]; // list of all components that have health
Stuff rest[]; // other entity information
IntRect healthUImap[]; // rectangle on where to draw health and index to health array
float * healthUIVBO;
...
void renderHealth() {
for (hm ... healthUImap...) {
int toDraw = health[hm->index];
...
healthUIVBO[i+0] = hm->left;
healthUIVBO[i+1] = hm->right;
...
}
}

void renderUI() {
renderBackground();
renderHealth();
renderText();

// send VBOs to GPU
}[/code]

Everything is explicit. And a trade off.

On one hand, need to hard-code individual elements like that is somewhat limiting. It becomes harder to add another arbitrary type. But at same time - how many distinct UI components do you need? TextArea, Button, List, Checkbox, Frame. Then a handful of manipulators, such as health rounding, effect decoration and perhaps a few more.

So what makes up an entity now? We can still have a strong HealthBar class. But it's completely unrelated to the above. It might be something like this:[code]class HealthBar {
int * value;
int * left, *right, *width, *height;
Texture * backgroundTexture;
}[/code]Decorate as needed, but it's completely separate from rest of logic. The grouping here is for our convenience, not convenience of renderer or simulation - those work completely differently. Above, boundaries could trivially be pointers into VBO itself.

Note that there is no ITextComponent which would be something like this:[code]class HealthTextComponent : ITextComponent {
private:
string text;
Rect bounds;
HealthComponent * phc;
virtual void setHealth(int health) {
int rounded = clampInt(health, phc->getMax(), phc->getMin());
text = intToStr(rounded);
}
virtual void render() {
renderTextBox(text, left, right, ....);
}
}[/code]Such decorations duplicate and replicate data and functionality. The do favor composition over inheritance, but don't add much, definitely not for the expenses incurred.


One very important requirement for such system is complete separation of creation vs. mutation. Unlike typical models where there would be smart pointers, listeners, observers, ...., actions which modify structure run only at pre-determined and well specified points. Adding a new UI element is perhaps done only after rendering a single frame.

Share this post


Link to post
Share on other sites
NetGnome    773
[quote]Which is RTTI. It can also be expressed differently, such as passing function pointers or delegates or using a switch. Different name, same thing.[/quote]

Sorry, by generic i didnt mean OO Generics like UIComonent<IUserInterface> where casting is type dynamic, but a container of interest to the system that can hold any reference to a UI element where casting is explicit via an implemented interface (i.e., no overhead other than method signatures) and thus can hold any "generic" ui element that implements that interface.

Share this post


Link to post
Share on other sites
Antheus    2409
[quote name='Net Gnome' timestamp='1326564917' post='4902702'] element that implements that interface.
[/quote]

Which is what dynamic dispatch (RTTI) is. C# makes it less visible, may offer certain optimizations, but it's there nonetheless.

Non-RTTI system can be fully resolved during compile time. Conversely, if I'm given an UIComponent, I would not be able to determine, at compile time, which .draw() method to use. It could be HealthBar.draw, abstract UIComponent.draw() or something else.

If that is possible, then there is no more parent component or an interface, just the concrete type, so adding an interface becomes redundant.

Share this post


Link to post
Share on other sites
NetGnome    773
The component is just a tag that contains data which identifies an entity as interesting to a system. In this case, the component's data package is a UI object and a UI system would be interested in that. This allows you to loosely tag a UI object to any entity in the entire game world in a decoupled manner. The overhead you're talking about in resolving an interface reference in c# is less than 1 thousandth of a millisecond, and is negligible for the extreme flexibility, data separation, and reduction in code burden it offers.

i have no idea what the c++ equivalent of a c# interface is... maybe a COM interface or abstract class, but its not clear how they relate. However, there is no dynamic dispatch here... that is done by either DynamicObject, the dynamic keyword, or the various reflection utilities in c#. I believe c# Interfaces are indeed known at compile time, whereas c++ (com interface) is not, due to the virtual keyword for its members. c# doesnt virtualize the interface members.

edit: didnt want to sound paternizing or argumentative, so i tried to clean up my wording. If c# interfaces do employ RTTI mechanics, they are damn efficient at it and quite hidden.

Share this post


Link to post
Share on other sites
Antheus    2409
[quote name='Net Gnome' timestamp='1326573663' post='4902755']
The overhead you're talking about in resolving an interface reference in c# is less than 1 thousandth of a millisecond, and is negligible for the extreme flexibility, data separation, and reduction in code burden it offers.[/quote]

Yes. But that is dynamic type that is resolved through RTTI during runtime. This is not "without RTTI".

[quote]there is no dynamic dispatch here...[/quote]

Anything that has override, virtual, abstract or anything similar in front of method name is dynamic dispatch.

[quote]Interfaces are indeed known at compile time.[/quote]

Yes - but not the concrete type. Anything that derives from an interface is dynamically dispatched. You cannot determine which implementation a given instance will have during compile time.

An example:[code]interface IFoo {
void foo();
}
class Bar : IFoo {
void foo() {
print("Bar");
}
}
class Baz : IFoo {
void foo() {
print("Baz");
}
}[/code]Now I you are given an instance of IFoo x. What will calling x.foo() print?

Answer depends on type which was created or assigned during run-time. Or Run-time type information. Without RTTI, the quesiton can be answered without running the code.


Design of a system that does not use RTTI is quite different from one that does. RTTI can be encoded in many ways. One was shown in OP's original post. Another is to use one of built-in facilities for polymorphism. Yet another is COM. Pointers to functions can be stored.

All of these are same dynamic dispatch, just slightly different implementations.

The example I gave above does not use any RTTI at all which is why certain trade-offs have to be made when it comes to design.

Share this post


Link to post
Share on other sites
NetGnome    773
I guess our opinions differed from our differing understanding of the meanings of RTTI... I've always taken it as meaning introspection of a type during runtime via things like "typeof", "is", "invoke", lambda expressions, generics, reflection, etc., not exactly to the atomic level that you have. I agree i was in error about this (At some point, a class has to be chosen). I'm just curious as to why one would purposefully handicap themselves by not taking advantage of even the most basic of OO techniques (other than the obvious, dont over-use or abuse thier use). I understand that it gets complicated in c++, but its almost impossible to avoid OO in c# and therefore avoid RTTI.

edit: sorry for the constant changes, i've revised what i wanted to say, as i didnt want to come accross as flippant.

Share this post


Link to post
Share on other sites
swiftcoder    18426
[quote name='Net Gnome' timestamp='1326584461' post='4902799']
I guess our opinions differed from our differing understanding of the meanings of RTTI...[/quote]
C++ is to blame for a fair amount of this confusion - most of the advanced uses you mention require you to explicitly "enable RTTI" in the compiler settings, while polymorphic/dynamic dispatch does not. That's just a nomenclature issue, as those features were added later, and needed *additional* RTTI information to be encoded (above and beyond the information needed for polymorphic dispatch).

[quote]I'm just curious as to why one would purposefully handicap themselves by not taking advantage of even the most basic of OO techniques. Might as well leave c++ and go to back to something completely procedural by your definition of RTTI.[/quote]
Predictability. A program with all types resolved at compile time is provably correct, but as soon as you introduce dynamic types, that goes out the window.

Share this post


Link to post
Share on other sites
NetGnome    773
[quote]C++ is to blame for a fair amount of this confusion - most of the advanced uses you mention require you to explicitly "enable RTTI" in the compiler settings, while polymorphic/dynamic dispatch does not. That's just a nomenclature issue, as those features were added later, and needed *additional* RTTI information to be encoded (above and beyond the information needed for polymorphic dispatch).[/quote]

Ahh, that makes more sense then. It also explains why MS' documentation is basically completely devoid of it in mention.

[quote]Predictability. A program with all types resolved at compile time is provably correct, but as soon as you introduce dynamic types, that goes out the window.[/quote]

again, that also makes sense. It is one of the reasons i've purposefully avoided using c++ in my personal projects. its just not worth the time chasing pointers, etc. around for the slight performance increase over java or c# with its straightforward simplicity and debugging (for my uses anyway).

Thanks for the lesson [img]http://public.gamedev.net//public/style_emoticons/default/smile.png[/img]

Share this post


Link to post
Share on other sites
DjMaSh    198
[quote]

the systems would implement something like this:

[CODE]
//for a UI updating system:
protected override void process(Entity entity)
{
UIComponent ui = (UIComponent) uiMapper.get(entity);
ui.IUserInterface.update(entity);
}

//for a UI rendering system:
protected override void process(Entity entity)
{
UIComponent ui = (UIComponent) uiMapper.get(entity);
ui.IUserInterface.draw(entity);
}
[/CODE]

[/quote]

Interesting. So the ui system is a complete stand alone system that doesn't depend on the entity system. The entity system is just a thing layer on top to bind UI elements to game objects.

From your code, it looks like there is a many-one mapping between systems and components. I always thought of them as a 1-1 mapping. The many-one sounds much more flexible though. Im really digging this design.

In my experience, component systems have only been used to manage game objects like balls and rockets. UI, and game rules and various other 'managers' have always been implemented separately. Normally you have a 'world' which is your component system. Things external to the world are responsible for instantiating entities, like a spawn manager. This uglies things up a bit as you now have 2 worlds, the entity system, and the thing holding the entity system which contains the game rules. But what if the 'world' _was_ an entity? Game rules could be implemented as components: aispawncomponent, boobytrap component, gamerules component etc. This eliminates the outter world manager thing. To create the game you simply instantiate a world entity. in turn, that entity would create everything it needed. Also, creating a different game mode, but keeping the same core rules would just be a case of swapping components.

The thing i like about this is _everything_ is always contained within the entity system. there are no other external managers. The entity system would be used to create your splash screen, intro movie, main menu, the actual game, credits screen etc.

Does anyone have experience with this? It seems with this data driven design, the component systems can be anything at all. At which point does this paradigm fall over? is it possible to create EVERYTHING inside the entity system? Even create applications that dont resemble games using an entity system?

One more question, how do you manage the update order of the systems?

Share this post


Link to post
Share on other sites
NetGnome    773
[quote] So the ui system is a complete stand alone system that doesn't depend on the entity system.[/quote]

in that example, i guess it would be considered separate somewhat, in that the system istelf isnt performing the action, but is more of martialing/dispatching the UI elements. I would envision it as two martialing/dispatch systems, one to martial/dispatch updates (for input, translation, etc.) and one to martial/dispatch rendering.

[quote]The entity system is just a thing layer on top to bind UI elements to game objects.[/quote]

Exactly. Though a UI element could be almost anything in theory.

[quote]From your code, it looks like there is a many-one mapping between systems and components. I always thought of them as a 1-1 mapping. The many-one sounds much more flexible though.[/quote]

They can be both. It may make sense for a system to have a 1-1 relationship. Other systems may want to look at other components as well. Some components may not really belong to one system, but are shared among many (though i would tend to try to avoid these situations if possible). Basically, the architecture should support * - * relationships. This is set when the entity system is added to the system manager by defining which components this system has interest in, these components then get registered to this system in a way that pre-loads all the applicable entity references.

[quote] But what if the 'world' _was_ an entity? Game rules could be implemented as components: aispawncomponent, boobytrap component, gamerules component etc. This eliminates the outter world manager thing. To create the game you simply instantiate a world entity. in turn, that entity would create everything it needed. Also, creating a different game mode, but keeping the same core rules would just be a case of swapping components. [/quote]

The mists are clearing grasshopper [img]http://public.gamedev.net//public/style_emoticons/default/biggrin.png[/img]

[quote]The thing i like about this is _everything_ is always contained within the entity system. there are no other external managers. The entity system would be used to create your splash screen, intro movie, main menu, the actual game, credits screen etc.[/quote]

Yep, it most definitely could. Though some specialty systems like networking, etc. may need to be separated due to their independant loads.

[quote]Even create applications that dont resemble games using an entity system?[/quote]

Yes, the ECS concept originated from software engineering a while back. though its morphed and changed over the years. IBM's tool ClearQuest is an interesting example of an almost purely Data Driven App.

[quote]One more question, how do you manage the update order of the systems? [/quote]

most sytems are called with a system.process() call when we want them to process during a specific time during a cycle. However, systems usually inherit from several kinds of superclass which modify the process call stack to perform varying types of "should i process now" checks. Some examples are just your basic processing system (updates every cycle), intermittent processing system (iterates every certain number of cycles, or i should say, will iterate a portion of its entities every cycle), delayed processing system (waits for some sort of event or trigger for it to process), asymetric processors (runs all the entities in parallel), purely passive systems (another system should call its process method, as it wont be included in the standard update/draw cycle), etc...

updates handled for informing systems about entity changes are done through a staging process initiated by the ECS Instance. That staging process may or may not run depending on changes made during the last cycle (i.e., did we stage deletes or refreshes). Each major manager is told about the changes, and they each perform their internal updates/deletes as necessary. As for systems, the system manager issues a refresh/remove order to each of the systems it manages and then the basic entity system superclass/baseclass cleans up the internal data structures from which a derived system operates on. Also, since order in which the entities are deleted / refreshed is not important (since you're just registering / de-registering), this would be a good target for parallelism.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this