Jump to content
  • Advertisement
Sign in to follow this  
nsto119

Sharing data among objects in an engine...

This topic is 4456 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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?

Share this post


Link to post
Share on other sites
Advertisement
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.

Share this post


Link to post
Share on other sites
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)


Dictionary shared;

// init
shared.AddPair("Time", 0);

// engine wants to update time
int *time = shared.GetPtrToVal("Time");
(*time)++;

// subsystem wants the time
int time = shared.GetVal("Time");
cout << time;



That's a rough pseudo-code example of what this method would look like.

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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.



Share this post


Link to post
Share on other sites
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)

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
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:



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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Because there are simpler, cleaner, and more elegant solutions out there for most problems. When most people use Singletons, it usually seems like a "I'm presented with a problem so I'm going to use the first viable solution I can think of without considering anything else" kind of thing.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!