Page 5 of 5
Re: Component Systems (New Question)
Posted: Mon May 30, 2011 4:51 pm
by XianForce
Well, I thought it'd be a waste to start an entire new topic, when my question pertains to this topic.
Anyways, I started programming a simple Component Entity System, just so that I could see how I like it. Well, after getting through a bit of it, I my base Component class had a single pure virtual function: void OnUpdate(float deltaTime). Further into it, I noticed that I never had any code in my overridden OnUpdate functions in derived classes. For example, I created a RenderComponent which held a renderable object (I'm using SFML by the way), and a z-order. I couldn't have the components handle their own rendering, because I had to rearrange them by their z order, so things were rendered in the correct way. With a CollisionComponent, I needed the CollisionSystem to actually check for the collisions.
As I thought about this more and more, I realized that the OnUpdate function was essentially useless to me. Since the updating code was the same, I decided to just put it into the System that managed that component. So that System would iterate through each component and update it accordingly. In this way, each entity isn't updating it's own set of components, rather each component is being updated, independent of the entity.
Are there any real qualms to this design? I could easily force the OnUpdate in the Component, have the RenderSystem order them correctly, then have each RenderComponent render itself. And in the CollisionComponent, I suppose I'd simply have the System handle the detection, and the OnUpdate resolve the collision.
Sorry if this makes little sense, I'm on a lack of sleep, and I'm just turning this over in my mind, trying to decide if I should fit the Update function in, before I get too much farther in. I appreciate any response
Re: Component Systems (formerly: Component Oriented Programm
Posted: Mon May 30, 2011 7:09 pm
by Falco Girgis
Your assumptions are correct.
Especially in C++, there are generally "Systems" that serve as component managers for the very reasons you have just stated. A CollisionSystem manages CollisionComponents, an ItemSystem manages ItemComponents, etc.
In fully object-oriented languages such as C# and Java, you'll often see classes serving as their own systems through the use of static functions... For example, the CollisionComponent could have a static member called CollisionComponent::Update() that processes all collision components. This is generally prettier in Java/C#, because they have mechanisms to facilitate this such as static constructors, and static functions are stored/invoked in the same manner as member functions (rather than as glorified globals in C++).
However, you'll often find that when working with higher level languages, components will have their own OnUpdate functionality. In Unity3D, extendable scripting components are called Behaviors. "Behaviors" do have OnUpdate() functions along with other triggers that may be utilized. In Elysian Shadows, we implement something similar through Lua. No scripter is going to want to design a standalone system to manage their custom components. They shouldn't have to either, because a custom component is a rarity--an engine should offer any component that is consistently required. So there really is never a need for a System/Manager for extendable components anyway...
Re: Component Systems (formerly: Component Oriented Programm
Posted: Mon May 30, 2011 10:33 pm
by EccentricDuck
You know, I had never really considered designing my systems the way you mentioned. Aside from scripting and web stuff, I've been working mostly with Java lately (and up until my game was released I was spending a lot of time with C#). I've been approaching it more from the C++ way - creating separate classes that manage individual components (in my most recent cases those components would be things like system states, screens, and MIDI calls to the soundcard (the object/component would store data relevant to the instrument, pitch, etc)). It's always felt a little clunky and awkward since Java is, by nature, tightly encapsulated. The language just seems to lend itself more towards storing data within the objects/classes themselves rather than separate subsystems. The Java approach is also far more comfortable for the programmers I've been working with who, with one exception, had only used higher level scripting languages before learning Java.
Every bit of state would be stored within the objects themselves using booleans or integers (Enums would be nice, but hey), but I end up needing to add accessors on top of that to make their objects work with objects from other systems (example: our most recent project took key input and played sounds using MIDI while simultaneously recording the key presses and displaying visuals on the screen - and each thing had its own internal representation of that state because they were written by different programmers). On top of that, Java has no equivalent to the "Protected" modifier in C# which makes accessing common data from subclasses more roundabout than it needs to be. Why would I write a public accessor for something I only want referenced by subclasses? It seems to indicate that, when using Java, there must be another approach that fits better with the nature of the language.
Are you suggesting storing static members within the class of a particular component and calling a static function to update them? That would seem to mostly get rid of the awkward accessor issues, and it would allow each programmer to write their own unique approach without creating additional surface level complexity (eg. which functions do I call and in which order?). Using overarching systems that other programmers need to interact with doesn't seem to work well when working with a team in Java. Dealing with overall program state was, in my mind, the biggest obstacle to expanding on our project (turning recording on/off, playback on/off, managing save states, which song was loaded, whether you were in purely playback mode (end user mode) or composing mode which is more of a sandbox). The two guys who came from more of a scripting background, while being decent programmers who got prototypes put together very quickly, were resistant to the idea of any overall state controlling their areas. One saw it as pulling control away from his "baby", and the other didn't see the purpose for it and felt like we just needed to go and slap it together and refactor later. The latter opinion is somewhat justified - it can be good to test your ideas before really committing yourself to them - but the biggest issue I was seeing was that our productivity had sharply declined once we tried to expand on the shaky foundation we'd created.
My point is that, I'm intrigued by what you just mentioned since it seems to provide a good way of keeping the component systems encapsulated while enforcing a common way of implementing them. Working with others, I appreciate encapsulation more than ever because it means that a) you don't have someone else breaking your stuff while trying to make their stuff work, b) you can get more to the meat of the problem you're dealing with without having to constantly refer to someone else, and c) your team doesn't have to constantly refactor because the below the surface details aren't a big issue for you if other programmers are providing a consistent interface for you to access.
Re: Component Systems (formerly: Component Oriented Programm
Posted: Mon May 30, 2011 10:51 pm
by XianForce
@Falco - Yeah, today I thought about it again, and I was thinking about Scripts as a main argument for putting the OnUpdate function back into the base class. But I had already planned to have some sort of ScriptingSystem to manage any component that has a script, so then again I find that components are more of a package of data, rather than a piece of functionality... If that makes sense.
Re: Component Systems (formerly: Component Oriented Programm
Posted: Tue May 31, 2011 2:29 am
by EccentricDuck
Sorry for kind of hijacking your question. From my limited experience, it's felt like it depends on how and where your data is represented and what language you are using. As I said, in Java, I find it difficult to separate the data from the containers they're in - and the language seems to warrant moving more functionality into the classes themselves rather than creating managing systems - but I never really figured out a good way of doing that.
In C# funny enough, I felt more comfortable using a system manager to manage those resources and update calls than I have in Java. Although very similar to Java, C# has a few notable differences that seem to make interacting with it feel different, including: the protected modifier (data members are accessible to subclasses without being public, thus giving more flexibility when overriding virtual methods with subclasses); structs (immutable, preventing external modification of data members that are exposed); and properties (which basically do the same thing as get/set methods, only they're more succinct and flexible). There might be other reasons that I can't point out, but the two languages just feel different to me - even though they are very alike in terms of their design and functionality.
Recently I wrote a script in Python to rip data out of HTML in webpages and I really appreciated the way the language felt for me while doing that - I really wouldn't want to do the same thing in Java. To me, C# feels almost semi-Pythonish in that sense, but with more low-level features like structs - whereas Java feels more static and restrictive like C++ except that nearly everything is in an object.
I can't speak to the virtues of C++ from my own experience since I haven't built any large projects with the language, but your point resonated with some experiences I had which is why I wanted to share that. I can however, speak from what I've read. Around the time I started this thread I was obsessively looking at articles from industry that talked about Component-Oriented Designs replacing the traditional deep inheritance hierarchies, like what the ES Team first used (of course what they're referring to is based in C++ since nearly every major console/PC game studio uses C++ for systems level programming). The message I kept running into was that if you're using that design, you should scrap the idea of having functionality in your classes and instead use the objects as data containers to be updated and manipulated by systems. That approach never quite seemed to mesh with Java, but I kept playing around with it anyway (I figured it was mostly a matter of gaining more experience with it). However, it's what a lot of articles published from industry seemed to recommend when using C++ so that's got to be worth something.
Re: Component Systems (formerly: Component Oriented Programm
Posted: Tue May 31, 2011 9:00 am
by XianForce
@EccentricDuck - Hmm, I didn't quite run into that conclusion when I was reading articles. It seemed like everyone did have functionality within components, but for certain reasons that I don't really remember, that was where the main complaints against them came. So that made me think about how I have components set up, and I don't see any problems with it.
Re: Component Systems (formerly: Component Oriented Programm
Posted: Tue May 31, 2011 2:59 pm
by EccentricDuck
Here's a link to a good powerpoint from the GDC:
http://www.google.ca/url?sa=t&source=we ... pl-bQB1LaQ
The entities or game objects contained no functionality, but their components did. The game objects were simply storage containers for behaviors and attributes.
Re: Component Systems (formerly: Component Oriented Programm
Posted: Tue May 31, 2011 3:01 pm
by Milch
@EccentricDuck
Maybe I've got something wrong, but there is a protected keyword in Java, and it does exactly that what you've talked about. (google it)
Re: Component Systems (formerly: Component Oriented Programm
Posted: Tue May 31, 2011 3:08 pm
by EccentricDuck
@Milch
It does have a protected modifier, but it functions differently than it does in C#. In Java, it makes the field accessible to everything within the package (essentially a namespace) but not to anything outside the package. In C#, it makes the field accessible to anything within the inheritance hierarchy. The latter is what made C# seem easier for creating richer virtual functions that really extended their parent class without opening fields or properties up to other outside classes.
I could use protected in Java and get the same effect if I had all my stuff separated into packages that no one else every touched, but in the group project I was working on there were some things that weren't that tightly separated (unless I were to make 1 package per class) and fields would invariably get accessed or appear like they should be accessed if I used the protected modifier in Java. We spent the first couple weeks putting things together so quickly that, invariably, stuff like that would happen - then that establishes the framework you build everything else on top of. It was a pain in the ass. Unfortunately, we just decided to throw it all together into 1 package from the beginning anyway so protected would have acted essentially the same as public (we started off with a simple IDE that made dealing with packages a bitch).
Re: Component Systems (formerly: Component Oriented Programm
Posted: Tue May 31, 2011 3:13 pm
by XianForce
Yeah, I saw that power point, it's good
. Another thing I was just considering though, is nesting components. Since components (the way I have them set up) are just packages of data, let's say I want to make a particle emitter. So I would think that would be a component that would be attached to wherever the particles were coming from... But then that means that You'd have a situation like:
Code: Select all
Player Entity
-RenderComponent
-BlahComponent
-ParticleComponent
-RenderComponent
-etc....
It just seems like this may be the wrong way to go about that...
Re: Component Systems (formerly: Component Oriented Programm
Posted: Thu Jun 02, 2011 1:30 am
by EccentricDuck
GyroVorbis wrote:
In fully object-oriented languages such as C# and Java, you'll often see classes serving as their own systems through the use of static functions... For example, the CollisionComponent could have a static member called CollisionComponent::Update() that processes all collision components. This is generally prettier in Java/C#, because they have mechanisms to facilitate this such as static constructors, and static functions are stored/invoked in the same manner as member functions (rather than as glorified globals in C++).
To ask more specific questions, would your class's static update function be the place where you would: a) determine which order in which to update components, b) determine what components to update, and c) be limited to only being called by a particular part of the code (so it's not as you said a glorified global as it would be in C++). For example, if I was using this approach in place of a screenmanager then would I use my base Screen class as a place to: a) keep track of a static stack of screens/layers and update them in order, b) determine not to update any buried screens, and c) only call update from one location to prevent from having it called more than once?
As I think more about it, the way I'm looking at this reminds me of using singletons (described once as a horrendous, fuck-ugly, bastardizing, brainless, degenerative, counterproductive design pattern). I couldn't use objects of the class in more than one context (essentially as if their manager was static) and I'd have to anally keep track of where I call update() since it's a static method that can be called anywhere and by anything. There must be something I'm missing here.