Sharing data among objects in an engine...
I'm sure this comes up often, but I've been reading up on different designs for engines (I really don't like that word, it's way overused) and none of them have really addressed the issue of sharing data among different subsystems and objects. The main place this has been a problem is timing, since objects can't really get the current time or framerate since they're not even really aware of the engine unless I make it a singleton or static class (something that's not feasible and would cause even more problems).
So, anyone know of any designs that work to solve this problem?
If you are worried about timing, I make all objects that need time-based updates a PollingObject. PollingObjects plug directly into a PollingEngine which keeps track of time. Every frame, it goes like this:
float time = GetTimeSomehow();
foreach PollingObject {
object->Update(time);
}
I register objects with the global polling engine with a global "fire and forget" function (sort of / long story short):
Thing* thing = new Thing();
CoreInterface::RegisterObject(thing);
// and we stop worrying about "thing" now :-)
I'm not saying you should make everything global, but in this particular case, having the core object processor have a registration function available globally might be the best way to go since virtually everything needs it. It would be wise, however, to not program objects themselves with "globality" in mind. Objects should be given (or get) the time but should not be dependent on your engine scheme.
float time = GetTimeSomehow();
foreach PollingObject {
object->Update(time);
}
I register objects with the global polling engine with a global "fire and forget" function (sort of / long story short):
Thing* thing = new Thing();
CoreInterface::RegisterObject(thing);
// and we stop worrying about "thing" now :-)
I'm not saying you should make everything global, but in this particular case, having the core object processor have a registration function available globally might be the best way to go since virtually everything needs it. It would be wise, however, to not program objects themselves with "globality" in mind. Objects should be given (or get) the time but should not be dependent on your engine scheme.
If you want to share a lot of data between subsystems that really aren't aware of each other, you can have something like a shared dictionary. Each subsystem can take a pointer to this dictionary as a parameter on initialization, and then when the subsystems need data they can just look it up in the dictionary. (If you want to use STL then an std::map would work)
That's a rough pseudo-code example of what this method would look like.
Dictionary shared;// initshared.AddPair("Time", 0);// engine wants to update timeint *time = shared.GetPtrToVal("Time");(*time)++;// subsystem wants the timeint time = shared.GetVal("Time");cout << time;
That's a rough pseudo-code example of what this method would look like.
My engine uses processes (or managers, as I call them) to manage (go figure) the subsystems. The engine class contains the instances of these managers and common useful tools, like a time class instance. When the engine updates a process / manager, it simply passes the it the timer's GetDeltaTime() or GetCurrentTime() method, depending on what it requires. The process / manager then passes that time variable onto any piece of the subsystem that needs it. For instance, all entities that move with velocity and acceleration need deltaTime to integrate correctly. So, the the EntityManager class has an update method that takes a float deltaTime parameter. In the update method, the EntityManager simply loops through all the entities it manages and calls their Update or Move or whatever method you have the moves them over time, passing the deltaTime variable. This way sounds like it takes up as much time as the one above, but doesn't require the space overhead of storing the time variable in each class.
Another way that is slightly more complicated, but might work well is to make a TimedObject class that contains a static reference to the Timer class's deltaTime variable. Since the Timer's deltaTime variable is updated every frame, the TimedObject always has the most recent time. Then, just have any class that needs the deltaTime to inherit from that TimedObject base class. Then, it has it any time it needs, without having to update anything else, or pass anything at all.
Anyways, good luck.
- Enosch
Another way that is slightly more complicated, but might work well is to make a TimedObject class that contains a static reference to the Timer class's deltaTime variable. Since the Timer's deltaTime variable is updated every frame, the TimedObject always has the most recent time. Then, just have any class that needs the deltaTime to inherit from that TimedObject base class. Then, it has it any time it needs, without having to update anything else, or pass anything at all.
Anyways, good luck.
- Enosch
If I am reading this correctly I am assuming you need a central timing system that all/some other objects need access to.
As has been mentioned in this thread earlier one way to do this is to have the time dependent objects have the timer variable passed to its constructor so that it has access to its public functions.
I've used this format with my DirectX Base Class so that all DirectX based objects have access to the basic information like the device or parameters.
Or have the timing object be a base class for all time dependent objects and thus have access to its own timing system.
I use this functionality with my transformable objects like the camera or the plane.
As has been mentioned in this thread earlier one way to do this is to have the time dependent objects have the timer variable passed to its constructor so that it has access to its public functions.
I've used this format with my DirectX Base Class so that all DirectX based objects have access to the basic information like the device or parameters.
Or have the timing object be a base class for all time dependent objects and thus have access to its own timing system.
I use this functionality with my transformable objects like the camera or the plane.
You might also want to consider a central message queue of some type, and just pass messages between your various components. I believe there's a good article on it in Game Programming Gems 4, and you can probably find good articles on it elsewhere.
(I really should write an article on it)
(I really should write an article on it)
Quote:Original post by Ravuya
You might also want to consider a central message queue of some type, and just pass messages between your various components. I believe there's a good article on it in Game Programming Gems 4, and you can probably find good articles on it elsewhere.
(I really should write an article on it)
Yes, I had thought of some kind of message queue. At this point though, I'm ready to redesign the whole thing. I neglected to properly plan this project, and just loosly based it off of Enginuity, but luckily I just started two days ago so it's not a whole lot of work to throw away. I think I'll take a look at some other designs and see what I like best. Any engine design in particular that you guys would recommend?
Edit: Also, anyone seen any tutorials around here that go into detail on creating a Quake-style console using streams for input/output? I had the idea of making the console, but only the back end, and exposing the streams so I could, for example, easily choose to either have the stream write to the screen or a file or something.
[Edited by - nsto119 on June 1, 2006 5:13:09 PM]
Hows this idea:
Have a static class, named Globals or something. It would hold an instance of the engine class. Since the class is static, everyone would have access to it. Something like this:
The only downside I can see to this is having to type so much. For example, to get the world matrix, I'd have to type Globals.Engine.Renderer.Transform.World.
Another thing I've thought about is having base classes with a static references to the subsystems they need.
Have a static class, named Globals or something. It would hold an instance of the engine class. Since the class is static, everyone would have access to it. Something like this:
static class Globals{ private static Engine engine; static Globals( ) { engine = new Engine( /*args*/ ); } public Engine Engine { get { return engine; } } static void Main( string[] args ) { Application.Run( engine ); }}
The only downside I can see to this is having to type so much. For example, to get the world matrix, I'd have to type Globals.Engine.Renderer.Transform.World.
Another thing I've thought about is having base classes with a static references to the subsystems they need.
I did go the way of the central Engine class (which is a singleton). It has all my current time information, command line arguments, and a multitude of things that other subsystems would need.
Why isn't it feasible to have a singleton? If it's the generic "they do two things; classes should do one" argument or some other design principle... Be sure you realize that having code that works and is readable is more important than following abstract design principles. There are no rules set in stone.
Why isn't it feasible to have a singleton? If it's the generic "they do two things; classes should do one" argument or some other design principle... Be sure you realize that having code that works and is readable is more important than following abstract design principles. There are no rules set in stone.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement