I think the main reason for Unity to use references to all components is performance. You don't have to iterate over the components to find the right one.
My method is not iterative either. At least components that are "built in" to the engine are stored as a static array that may be accessed by:
C++ and Lua "Behaviors" (components that are extending the engine) are stored in a std::map and must be iterated through (which is the same as Unity). I'm pretty sure that they did it just for convenience and code readability.
THANK YOU!! that is such a great implementation :D
for the components do you add properties to them or do you inherit from them in a class like SpriteComponent : public Component... the onlything with doing that is you would have to do somekind of templating to return the correct type of component so if you use properties you would have to make a base class that was not templated with minimal info then inherit from that and make the child a templated class so that you could store them in the same array and template them on return... you would have to iterate through that wouldent you? well whatever. im still trying to figure it out but i appreciate you're help
WSPSNIPER wrote:for the components do you add properties to them or do you inherit from them in a class like SpriteComponent : public Component... the onlything with doing that is you would have to do somekind of templating to return the correct type of component so if you use properties you would have to make a base class that was not templated with minimal info then inherit from that and make the child a templated class so that you could store them in the same array and template them on return... you would have to iterate through that wouldent you? well whatever. im still trying to figure it out but i appreciate you're help
I implement them via inheritance--it allows you to define (pure virtual functions) required for each component (Load(), Save(), canAddTo(), etc) and takes much less work (for the programmer). Now these "specific" components are polymorphed back to the Component class before they're stored in the Entity's array.
This definitely has the disadvantage of:
1) Either you have to define a separate templated getCompenent<type>() function for every component or
2) You have to cast them to their more specific forms after using getComponent().
Either way is kind of a pain in the ass, but hey, we're implementing an extremely Object-Oriented system with a language that has no default runtime-type identification... at least it's going to perform well. :D
GyroVorbis wrote:Either way is kind of a pain in the ass, but hey, we're implementing an extremely Object-Oriented system with a language that has no default runtime-type identification... at least it's going to perform well. :D
How does C# compare in this sense? I've never really done any type identification, but I'm not sure if that's because it's not necessary or I just write unsafe code. Another possibility is that I've only made limited use of polymorphism so it just hasn't come up much.
WSPSNIPER wrote:for the components do you add properties to them or do you inherit from them in a class like SpriteComponent : public Component... the onlything with doing that is you would have to do somekind of templating to return the correct type of component so if you use properties you would have to make a base class that was not templated with minimal info then inherit from that and make the child a templated class so that you could store them in the same array and template them on return... you would have to iterate through that wouldent you? well whatever. im still trying to figure it out but i appreciate you're help
I implement them via inheritance--it allows you to define (pure virtual functions) required for each component (Load(), Save(), canAddTo(), etc) and takes much less work (for the programmer). Now these "specific" components are polymorphed back to the Component class before they're stored in the Entity's array.
This definitely has the disadvantage of:
1) Either you have to define a separate templated getCompenent<type>() function for every component or
2) You have to cast them to their more specific forms after using getComponent().
Either way is kind of a pain in the ass, but hey, we're implementing an extremely Object-Oriented system with a language that has no default runtime-type identification... at least it's going to perform well. :D
In the ES engine, we use the second approach.
nice the first way is how i was implementing it before. basically it would just you would just call entity->getComponent<RenderingComp>("Rendering"); but now that you showed me the enum implementation it looks like this entity->getComponent<RenderingComp>(Component::Rendering) but i dont think im going to have a rendering component any more because i will have a rendering system that implements the sprite, animation, and all other components needed to render.
could you explain the second method a bit more?
would you go (RenderingComp*)entity->getComponent(Component::Rendering)? well... that is almost the same as the templated right? well im sorry i dont understand
In my system I have to iterate over the components, because I have the entity system as seperate lib where the user can add custom components. So I can't make an enum including all the different components => templated GetComponent().
K-Bal wrote:In my system I have to iterate over the components, because I have the entity system as seperate lib where the user can add custom components. So I can't make an enum including all the different components => templated GetComponent().
ya, thats prob a good idea but for now im just going to use an enum because i am making a concrete engine that wont be reused by anyone but me lol well i am making it open sourced like i do all my projects but thats their problem then :D
K-Bal wrote:In my system I have to iterate over the components, because I have the entity system as seperate lib where the user can add custom components. So I can't make an enum including all the different components => templated GetComponent().
Ditto. It's really unavoidable, haha.
That's why I made the distinction in the ES engine between our "built-in" components, and client "behaviors" that can be C++/Lua components.
GyroVorbis wrote:Either way is kind of a pain in the ass, but hey, we're implementing an extremely Object-Oriented system with a language that has no default runtime-type identification... at least it's going to perform well. :D
How does C# compare in this sense? I've never really done any type identification, but I'm not sure if that's because it's not necessary or I just write unsafe code. Another possibility is that I've only made limited use of polymorphism so it just hasn't come up much.
That's an interesting question. If you've ever used the Unity3D engine (I compare lots of what they do to what we do in ES as kind of a "Unity2D"), you will immediately notice subtle differences between C# and C++ implementations.
With regards to something like a component manager, it's a little prettier on the front-end, because of runtime type identification. In C#, you can store/access these components by type AND autopolymorph them back to their specific types when returning a component.
This method is still iterative, so there is definitely a performance hit, but it's prettier... that's pretty much the tradeoff in a nutshell.
GyroVorbis wrote:Either way is kind of a pain in the ass, but hey, we're implementing an extremely Object-Oriented system with a language that has no default runtime-type identification... at least it's going to perform well. :D
How does C# compare in this sense? I've never really done any type identification, but I'm not sure if that's because it's not necessary or I just write unsafe code. Another possibility is that I've only made limited use of polymorphism so it just hasn't come up much.
That's an interesting question. If you've ever used the Unity3D engine (I compare lots of what they do to what we do in ES as kind of a "Unity2D"), you will immediately notice subtle differences between C# and C++ implementations.
With regards to something like a component manager, it's a little prettier on the front-end, because of runtime type identification. In C#, you can store/access these components by type AND autopolymorph them back to their specific types when returning a component.
This method is still iterative, so there is definitely a performance hit, but it's prettier... that's pretty much the tradeoff in a nutshell.
So if I'm understanding this correctly, in C# it's more flexible because it automatically iterates over all present inherited classes when polymorphism is used (to check for what type it is), but that also gives it a performance hit for the same reason?
Hmm... as far as autopolymorphing them back, I just assumed that was the way it was normally done (that's the only way I've really used polymorphism so far). Doing something like having a fire function based upon a certain input where it looks for type "Projectile" and returns "Bullet" or "Missile" (btw, that was along the lines of an idea I was previously pursuing with a "simple" 3D flight shooter - I cut that before projectiles were finished for a simpler concept).
I just recognized a case where I am actually using type identification (these discussions really are good for learning). When I call ProcessPackets() for my networking setup I:
a) check for available incoming data,
b) type check each packet to see what kind of packet it is,
c) then throw the result into a switch...case statement for the different packet types in my enum list.
I didn't really consciously recognize it before - I borrowed a lot of the networking code and have been dissecting it and modifying it for my needs. Cool
Asked my Comp Sci instructor about type checking today. It took a bit to get it out of him but he was of the firm opinion that type-checking should only be done in "extreme" cases. Of course, I'm in a Java class where we haven't actually written anything (today, 3 classes and 1 lab in, he demoed how a bank account class would look).
All we've done is created and played with objects of pre-written code. I can see the validity in trying to teach the big picture, but I think it has major flaws. While talking about how we'd design a bank account class in groups (not even considering data types, just the names of fields and methods) I was holding myself back from arguing with one girl in our group who kept insisting that methods have to be added after we create an object of the class. I was trying to understand where she was coming from, but it was hard when she was saying "no, don't add methods yet, we need to create an object of the class first" (keeping in mind as well that this is being done on paper). I can't entirely blame her, but I think the approach to teaching that is being used is flawed. We'll see as the course goes on...
Going back to type checking: The way I've been seeing it is that type checking allows greater use of polymorphism than would otherwise be an option, which in many cases is both a very practical and safe design decision isn't it? A lot of the class today was spent emphasizing proper planning and design (mentioning things like the Y2K bug and how it cost billions of dollars to edit legacy code that used 2 digits for year). One of his big points was on making it so it's maintainable. Wouldn't type checking be highly maintable? It's easily extendable for one (adding to a static array/enum and adding any corresponding methods would be simpler than having to go back and rewrite other stuff... kind of like a component system).
Another thing, regarding the teaching aspect, isn't talking about proper design of a bank account overkill when most of the class can't even write a hello world application? They should be using Python or something like that if they want to simplify things like data types and scope (every field is private and every method is public so far... I doubt most of the class understands why). He even talked today about why we're learning Java, and it's because he wants to teach good coding practice in a language that is often used for large-scale software. I get his intentions... it just seems so backwards to be teaching design when the students don't know what the pieces mean. I think everything would be a bit clearer if the class had at least written a hello world application. Hell, it would be the perfect match for BlueJ where they create an app with 1 string, 1 get method, and 1 constructor (make a basic overview of those 3 things assigned reading), then create an object of it (without having to worry about creating one in another class you just create one for playing around with in BlueJ) and use that method. It would be simple, would give some hands on experience with writing a field, a method, 1 public and 1 private accessor and it would keep data types simple (just string).
I'm all for a balanced approach, learning the little bits then seeing where they fit in with everything else helped me enormously when I was teaching myself - but when I found myself lacking understanding of how to communicate between classes I stepped back and thought about design... and when I didn't understand what exactly was going on at a lower level I dove in and made sure that I DID understand exactly what was happening (I've come to understand why there's a whiteboard in pretty much every AiGD and ES video - now I always have one when I'm coding). I mean, really, I can understand why teaching just the nitty gritty to people who don't know what to do with it can be difficult... but what good is teaching what you can do with it without teaching how to do it? As far as learning goes, I think that both practice and making mental associations is hugely important and I don't see that being taken into account here (of course, I don't think most university courses take this into account).
I know this topic has been dead awhile, but since we had a pretty good discussion going I thought it would be a good idea to keep this in the same thread. I was wondering about what the speed of a data-driven component system would be like. Previously when I was looking at it, one of the downsides to a component driven approach was that there tended to be more overhead (which makes sense when you're allocating that many new objects to the heap and having to sort through and keep track of all applicable components for all your entities).
Compared to a strong inheritance approach however, wouldn't a data-driven system be potentially much faster? Since a component system is really just treating entities as data storage containers anyway, why not just make them data like how you'd structure it in a database. Attach a key to each entity and have it store whatever "components" are attached to each entity. This seems to me to be far easier than doing it with a regular object approach. Also, it would be far easier to actually put something like that in a real database if that was an eventual goal and well as to set up various systems that would use that data (like networking systems for multiplayer/external communication, collision detection, etc). It would centralize your important data in an organized fashion for fast and easy access. In a game, entities interact with so many different systems that many object-oriented approaches get ugly and break down encapsulation anyway.
If that works well but you're worried about breaking encapsulation (what if something gets accessed and changed somewhere it's not supposed to), then have a log system that tracks access to the data broken down by entity/component (allowing you to track when something is going awry with some entity or system).
Thoughts?
EDIT: I know I'm being rather vague when I talk about storing entities/components as data, as there are dozens of ways you could approach that I'm sure. Essentially I'm talking about any model that involves something akin to how a database would look with keys that reference particular parts of the data that are associated with other data (in a simple example like a phone book, you might have a key referencing a person's name, with a first name, last name, phone #, address, etc, stored in there). I suppose this opens up a whole new question as to which way you store this, but obviously you'd want it to be dynamic so that you could still retain the full benefits of being able to create new entities without changing something inside your "database".
(I hope I'm not doing a disservice by posting this without adding anything, for I currently don't have anything to add, but I feel that this points in the direction of the topic I re-opened)