Jump to content
  • Advertisement
Sign in to follow this  
nilkn

Message-Based Communication Systems

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

Abstract What are the advantages of message-based methods of communication between disparate classes/components? Do such methods provide media through which more advanced logistics can be implemented, or do they merely cloake the code in an unnecessary layer of abstraction, needlessly over-complicating everything?
A few months ago I bought AI Game Engine Programming by Brian Schwab and found it a very insightful, authoratative text, to say the least. Chapter 17 of this book discusses implementing a message pump which propagates messages throughout the various components of the program. This technique allows classes to communicate without knowing who their talking with. Example code: Case One:
void AIController::Update(float TimeStep)
{

     // ...

     foreach IAIAgent* agent in m_agentList {

          // ...
          if ((agent->GetPos() - Game::GetPlayer()->GetPos()).Length() <= Game::GetAIDistanceThreshold())
               MessagePump::SendMessage("Player within threshold", agent->GetUniqueID());
     }

     // ...
}
However, herein lies my problem. The above task could easily be accomplished by simply giving IAIAgent a method to call when the player comes within the set threshold: Case Two:
void AIController::Update(float TimeStep)
{

     // ...

     foreach IAIAgent* agent in m_agentList {

          // ...
          if ((agent->GetPos() - Game::GetPlayer()->GetPos()).Length() <= Game::GetAIDistanceThreshold()) {

               // There's not much point in using the message pump here.
               // We already have pointers to the constituents of the interaction.
               // Therefore, why not just do something like this:
               agent->PlayerWithinThreshold();
          }
     }

     // ...
}
Perhaps the above code could be cleaned up and generalized a bit by giving each IAIAgent it's own 'mini' message pump: Case Three:
// Instead of making an explicit public method for each possible message, do something like this:
agent->Notify("Player Within Threshold");

// This way the specific class would be responsible for delegating out the message handlers however it likes.
// How messages are handled would be unknown to the outside world, just like it was before with the message pump.
Now, of course such a simple solution wouldn't work for a very high-level logistics problem. For example: imagine a game which takes place in a large, dynamic world; one in which AI agents are responsible for deciding what they do and how they do it. Now consider that the game is about a war in which two opposing factions try to collect the majority of a set amount of 'mystical orbs'. One application of a general-purpose message pump would be to notify all AI agents with a single call when a faction captures another Orb. The message could, for example, contain information as to which faction captured the Orb, the general location of the capture, and the ID of captor.
  • Of the three case's presented in the above section, which do you think is most suitable for the high-performance environment of game development and why?
  • If one were to use Case Two or Case Three, how might the final example of communication with multiple, unknown entities be accomplished? Should, perhaps, a stripped down global message pump be implemented which would only offer the most primitive services, lacking the niceties such as message priority, sorting, and arbitration? Or should a method be added to AIController which simply loops through all AI agents, calling their subsequent notificatory (is that a word?) methods?
  • What are the advantages, if any, of using a global message center for the more atomic-level tasks such as the one described in the first case? What are the disadvantages?
[Edited by - nilkn on June 12, 2005 3:22:17 PM]

Share this post


Link to post
Share on other sites
Advertisement
Are you familiar with the Observer design pattern? If so, do you understand the concept of Event-based Observers? Sounds like this is what you should look into for further study.

Any opinion I might offer on the subject is just that, as far as performance goes.

One way or another, though (of course), you should implement some type of asynchronous messages for user input (message pump). A program without something actively watching user input would be pretty useless ... lol.

Just thoughts.


Chad

Share this post


Link to post
Share on other sites
message based systems usually involve the loss of data types (which sometimes means casting and any data types), and loss of information.

Essentially a good design and interfaces is a lot safer and easier to implement.

Share this post


Link to post
Share on other sites
Eh, no replies? [might be by the time it's done, heh] I'll give this some shot, though I'm more interested in other replies rather than knowing much myself... So take all advice with a grain of salt.

Quote:
Original post by nilkn
Abstract
What are the advantages of message-based methods of communication between disparate classes/components?


Like most abstractions, it presents a unified interface between components and all the benefits therein. Things may be changed more easily in each class without impacting others, classes may be more easily reused since their only dependancy is on the messaging system, only the messaging system needs to be visible to the disparate classes.

Quote:


Do such methods provide media through which more advanced logistics can be implemented, or do they merely cloake the code in an unnecessary layer of abstraction, needlessly over-complicating everything?


I'd say somewhere in between. Abstraction has its uses, and save the developer a great amount of time debugging and/or re-writing depending on the scenario.

Quote:

*snip*
Example code:

Case One:
Case Two:
Case Three:


This seems like a fairly poor example. Messaging systems' main benefit comes from communication between otherwise independant components. Since AIController and AIAgent seem to be already interdependant, the messaging system is perhaps extraneous. To me, Case Two is the most appropriate for this particular example since that message is almost guaranteed to always originate from an AIController class. Nothing is gained from the added abstraction.

Quote:

*snip*

  • Of the three case's presented in the above section, which do you think is most suitable for the high-performance environment of game development and why?



I imagine all three are used to one degree or another. Case 1 is the general use case, and provides a great deal of versatility. Case 2 is useful where interdependant classes don't [or rather, an isolated sub-system doesn't] need the added abstraction of the system. Case 3 is useful when sub-systems/objects run independantly, but still need a queue system. I imagine any sort of multi-threaded environment employs such mini-queues.

Quote:


  • If one were to use Case Two or Case Three, how might the final example of communication with multiple, unknown entities be accomplished? Should, perhaps, a stripped down global message pump be implemented which would only offer the most primitive services, lacking the niceties such as message priority, sorting, and arbitration?

    Or should a method be added to
    AIController which simply loops through all AI agents, calling their subsequent notificatory (is that a word?) methods?




See above, a mix might be better.

Quote:

  • What are the advantages, if any, of using a global message center for the more atomic-level tasks such as the one described in the first case? What are the disadvantages?


I mentioned some advantages above. Disadvantages come from the slight obfuscation that abstraction may provide. The message movement and parsing will add some overhead to the action. A global message system is a lynchpin, and if not designed well, might impact every system in your application negatively.

Share this post


Link to post
Share on other sites
obfuscation was the word I was looking for - losing your data type and having to perform casts.

Share this post


Link to post
Share on other sites
Quote:
Original post by Genjix
obfuscation was the word I was looking for - losing your data type and having to perform casts.


Casting is not necissary if you're clever. c++ pure virtual base classes are good for these sort of interface definitions. C# I think has even better constructs to provide a messaging interface.

Share this post


Link to post
Share on other sites
Quote:
Original post by nilkn
Do such methods provide media through which more advanced logistics can be implemented, or do they merely cloake the code in an unnecessary layer of abstraction, needlessly over-complicating everything?


Personally I think there's not much point asking the question, as you've already clearly identified the pros and cons of the approach. Do you need those 'more advanced logistics'? If so, the messaging system helps keep things clean and flexible. If not, it's probably not adding much to your game.

The examples below where you remove the message queue, also remove the ability for 3rd party agents to act upon the message. Sometimes that doesn't matter, but other times you might want to emit a message where it's not trivial at the point of emission to know who is going to react to it, or how many will.

I think that drawing up a list of the event types you're likely to encounter can help you make a decision.

Share this post


Link to post
Share on other sites
Thanks for the replies!

To be honest, I pretty much made up my mind once I posted this thread, but this thread was less about me solving my problem and more about hearing people's opinions on the matter, which I'm definately still interested in.

Verg: I've heard of the Observer pattern, but haven't ever looked it up. I'll definately check it out now. Thanks for mentioning it [smile]

Genjix: Yep, that was one of my concerns. I figure if I design my interfaces properly, I won't have to mess with that... or at least I hope.

Telastyn: Awsome reply! You pretty much summed up all my questions. Just so you know, I chose the example because it's very closely related to the actual problem I was trying to solve. My main intent in making this thread was to find out if using a message system for such a task is worth it. You explained it quite nicely [grin]

Kylotan: Yes, I was basically already aware of all that. I mainly wanted the opinions of people experienced with messaging on whether it was worth using or not. The final example dealt with sending out messages to multiple, non-specific receivers.

Share this post


Link to post
Share on other sites
Bump. [smile] No one else has opinions on or past experience with message systems?

I've decided to go with a mix of Case 1 and Case 3. I believe it will provide me with enough versatility to reuse on later projects, yet enough simplicity and convenience to avoid using a global message pump for everything little interaction/message.

Share this post


Link to post
Share on other sites
Quote:
Original post by nilkn
Bump. [smile] No one else has opinions on or past experience with message systems?


I haven't read all the thread so i'm sorry if this is useless to you but i think if you are going to use a message based for internal communication of objects i think your wasting your time. As mentioned already use some form of observer pattern or signals & slots framework, or something similar, using message-based for that is going over the top unnessecarily.

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!