Sign in to follow this  

Event Management/Queue Design/Pitfalls?

This topic is 481 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

Hi

 

I'm now starting to move towards content development for my game, as such, I'd like to ensure a clear and concise execution of an event management system.  I have some ideas already on what I want to achieve and I've sketched them up a few times, trying to ensure that the execution is simple and limited.

 

I've read a few different design sites etc, so I am aware of some short comings.   But as a hobbyist developer, you do find sometimes some weird and interesting ways to get yourself in a bind.

 

I'm thinking (I have alot of dot points but I won't bore people):

 

- In it's own thread (running in parallel to main game).

- Buffering and arms length exchange/processing of messages (for the loose coupling as would be expected) 

- Register/Post/Trigger functions.

- Initially a simple set of event functionality (try and make this a success). 

- C# game btw - events can be as simple as notifying of enemy death.  I expect more complex functionality like Mission success/failure criteria to come later.

 

Now, it's very general.  But as I approach my design, I'm interested in what others have done in terms of approach and with all executions, what did you find worked or didn't work in your situation.    And I'm speaking more from a design specific view.

 

Thanks in advance for any answers.

Edited by ErnieDingo

Share this post


Link to post
Share on other sites

- In it's own thread (running in parallel to main game).
- Buffering and arms length exchange/processing of messages (for the loose coupling as would be expected) 
- Register/Post/Trigger functions.
- Initially a simple set of event functionality (try and make this a success). 
- C# game btw - events can be as simple as notifying of enemy death.  I expect more complex functionality like Mission success/failure criteria to come later.


- Why threads? Does it need to be threaded?
- Why buffering? Why messages?
- Why not the typical C# 'event' keyword?
- Yes, start simple ("use the simplest thing that could possibly work") and only add complexity when you know you need it.


It sounds like you're trying to make your own Actor Model (https://en.wikipedia.org/wiki/Actor_model). They're generally completely overkill for game clients. They're more useful for distributed computing on server clusters. Edited by Nypyren

Share this post


Link to post
Share on other sites

 

- In it's own thread (running in parallel to main game).
- Buffering and arms length exchange/processing of messages (for the loose coupling as would be expected) 
- Register/Post/Trigger functions.
- Initially a simple set of event functionality (try and make this a success). 
- C# game btw - events can be as simple as notifying of enemy death.  I expect more complex functionality like Mission success/failure criteria to come later.


- Why threads? Does it need to be threaded?
- Why buffering? Why messages?
- Why not the typical C# 'event' keyword?
- Yes, start simple ("use the simplest thing that could possibly work") and only add complexity when you know you need it.


It sounds like you're trying to make your own Actor Model (https://en.wikipedia.org/wiki/Actor_model). They're generally completely overkill for game clients. They're more useful for distributed computing on server clusters.

 

 

- The threading is really so that it can run parallel to the main game loop.  It is to do with the number of objects I will have active in the world and I am thinking of ways of ensuring it doesn't impact performance of the main game loop.

- More to do with that fact if I go multithreaded.  For starters I don't need to and buffers/queues are necessary.  Im just looking at concurrency down the track.

- The C# Event model is missing a few functions I would like priority, delete an event, time delayed events (especially in my game when I need to fire a "Mission failed" due to time lapse between trigger and completion of event.  I know that I wont be using these at the start, but part of my design calls on this later to be implemented for my game.

- yes, my model seems to share some of the traits of that model.

 

Thanks for the info though, it has added much to what I am thinking about.

Share this post


Link to post
Share on other sites
Priority queues can handle the priority and time-delayed events. Despite their name they are usually implemented using a "binary heap", which are just binary trees with a parent/child ordering scheme that makes them really fast (and simple!) to check and update. If you had a single binary heap for timed events, you would barely need any processing time whatsoever to deal with it on the main thread.

I'm still not sure what kind of heavy processing you might want to do on a background thread. All gameplay events I've dealt with have been simple and fast enough that we've never bothered trying to thread them. The extra work of coordinating the threads seems like it might overwhelm any gains the second thread would have.

I mostly see instant events (which either use a C# 'event' or some similar type of callback) or timed ones (which use a priority queue ordered soonest-first). Anything on a thread usually needs some kind of case-by-case analysis to make sure race conditions don't occur. Threading usually falls into two categories - shared data with locks, or immutable data without. I don't see how you'd make a general purpose 'execute arbitrary code' event system multithreaded without ending up with a full actor system, since locking all over the place leads to overhead or deadlock hell.

Maybe an actor system would be the best for you - it's hard to say without knowing your whole game plan. The nice thing about actor systems is that when you get them working right, they scale up to any number of CPU cores without any tweaking. It's just kind of a pain to deal with the other constraints they place on you.

You could try looking at a few existing frameworks and see if they make sense for you.
TPL Dataflow
Akka.NET

...or even just using the ThreadPool to start up short-lived Tasks with async/await might work. Edited by Nypyren

Share this post


Link to post
Share on other sites

I think Nypyren is right on the money - the message queue itself is so lightweight compared to the rest of your game that putting it on a new thread gains you nothing. That may not be the case for the actions you have to take as a result of those messages, but for all we know that might require locking the main thread to execute them anyway. So you need to dig deeper before you know what is right here.

 

Personally I don't think that buffered messages are a good thing; decoupling cause from effect makes debugging very awkward. So I prefer synchronous messages where possible.

Share this post


Link to post
Share on other sites

Thanks guys, I will for now just go for the same thread. 

 

The thread pool might be good for specific events, if I want to possibly have timed events, fire them in there own thread and they pass back their trigger at the end of the time.  But im sort of faced with thread management a bit more in that case.  

 

I will for now just do this single threaded, if it gets to the point where it does cause performance issues I can re-evaluate.  

 

I will definitely look at the binary heap tree for the event timing component.

 

And as you mentioned, the locking might be an issue on processing events and sending them to the various subscribed actors (hence why I was thinking of buffered queues etc).

 

My plan at the moment for my game - I've built the graphics component to a point that im flying around my world quite happily (And I have some enemies flying around in circles due to no AI!).  Its sort of a 1942 / Raid on bungling bay type game.  Basically I have been focusing on the graphics engine and editor for the last 2 months to get the graphics component working, my voxelised terrain works and I have my collision detection framework in place.  But, still working on my editor also, the way im working it is that a map may have multiple missions, as such I would like to load different scenario's in which would include event flows and triggers for various components.

 

as mentioned, I will start with some simple event management stuff and grow it.  The main focus will be to build a model that is extensible. 

 

Thanks all for this!  Your input has been heartening.

Share this post


Link to post
Share on other sites

Buffering lets you move the message around more efficiently, but the interesting part is how you act on the message, and then you're potentially back in locking-hell.

 

I also strongly recommend against using threads for timed events. Just use a priority queue and pick the events off when they become 'ripe'.

Share this post


Link to post
Share on other sites

If you're going to do threading in C#/.NET, think long and hard over whether you need to use real, dedicated threads, or if you can get away with using ThreadPool.QueueUserWorkItem() or Task.Run().  Unless you are doing something very long-lived, using the old Thread style is usually more complicated and error-prone than it needs to be.

Share this post


Link to post
Share on other sites

This topic is 481 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.

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