• Advertisement
  • entries
  • comments
  • views

More on MonoGame/XNA Components

Sign in to follow this  


Have been slowly plugging away at my Combat Prototype for my game. I've kept a clean separation of the "Engine" and "Game", with each being in separate assemblies. The Engine code is the foundations - A Unity-like GameObject + component model that sits on top of MonoGame (or XNA). I'm not going to talk about the game part, but the continuation of the Engine core.


Lately, I've added in a Messaging system. This was primarily due to me needing to communicate between GameObjects. For component-component communication on the same object, I'm just referencing the components directly. I decided to go messaging for intra-object communication because I really didn't want to start tightly coupling other objects to each other. My messaging implementation is different to Unity's. I'll talk about that here.

When a component wants to hook a message, it must call "RegisterMessageHandler" on the GameObject it's attached to.

This has the following prototype:void RegisterMessageHandler(string messageType, Action handler);

As you can see, it takes a handler function as a parameter. The GameObject itself then listens to any messages hooked by the components and routes them to each component when received.

Each message must implement the interface IGameObjectMessage, which has a single required property - "MessageName". I'm tempted to remove this requirement entirely and make it more like how Components work - requiring the messages to be bound by the message Type. This would give me something such as:
void RegisterMessageHandler(Action);
This feels more elegant. However, this may create an issue if the components are destroyed and don't unhook the messages first. I'm contemplating using C#'s event system and following a Weak Event Pattern. Thoughts are appreciated.

There's a few ways to send a message to other objects. I'll list them out:

  • SendMessage - Sends a message to a particular GameObject
  • BroadcastMessage - Sends a message to a GameObject and all its children
  • SendMessageUpwards - Sends the message to the GameObject's parent
  • BroadcastMessageUpwards - Sends the message to the GameObject's parent and it's ancestors.

    One thing I'm debating with the Broadcast options is whether they should cascade all the way up and/or down the tree to children of children, etc.

    I've also got a GameObjectGraph. Basically, a way of storing and accessing my "root" objects. I'm currently figuring out a nice way of exposing this to the world other than using a Singleton. It's likely to appear as a property on the GameObject in some way.

    I need this because it acts as a sort of scene graph. It is the root object of the "world" and is called when I want to both Update() and Render() my scene. It also acts a place to fire global messages to notify all GameObjects in the world about something. At this level, I have:

    • BroadcastMessage - sends a message immediately to all objects, starting at the root and cascading downwards
    • QueueBroadcastMessage - drops a message onto a queue to be sent the next tick, before Update() is called

      The message handlers themselves have the signature:[code=:0]void SomeHandler(IGameObject sender, IGameObjectMessage message);
      The first parameter is the GameObject which sent the message. The astute of you will realise that it's actually a Component which sends messages and not the GameObject. It's debatable whether the first parameter should reference the component instead of the GameObject, as this would open up component-component direct communications.


      I've added a simple Tag collection to each object. These are text labels which can be searched on. A GameObject can have as many as needed. I currently use them for Linq queries over child objects:
      [code=:0]foreach(var child in this.Children.Where( (o) => o.HasTag("sometag") ){ // do something with tagged object}

      I'm contemplating extending this system to become a Triple Tag, basically: namespace:predicate=value. This would make things nice and flexible, especially when combined with Linq queries. For example, if I had two sides in the game and I wanted to find all units of type "tank", I could write a Linq query such as:
      [code=:0]foreach(var tank in this.Children.Where( (o) => o.HasTagNamespace("SideA") && o.HasTagPredicate("UnitType") && o.HasTagValue("Tank")){}

      That's about it for now. There's a few current niggles and areas I need to start looking into. These are:

      • Object creation via cloning (allows me to have Prefabs)
      • Object destruction (queue to kill next frame)
      • Object serialisation to JSON/BSON (allows me to save/load object definitions from files)
      • General object management and tracking.

        The current systemis nice enough, I guess - it has quite a few rough edges and things I'm changing as I go on - I already plan on reusing this part of the system in other projects. I'm also contemplating open sourcing it on GitHub, I'm not sure though...
Sign in to follow this  

1 Comment

Recommended Comments

Note, combining the "HasTagX, Y and Z" method calls as you have shown doesn't do what you would want.  You don't want a "has SOMETHING with namespace X" and "SOMETHING with predicate Y" probably.  would want a tag row where all 3 are true for the same row.  So you need overloads that take multiple parameters, like "HasTagPredicate(namespace, predicate)" for a 2 parter and "HasTagValue(namespace, predicate, value)" for a 3 parter.


good luck.

Share this comment

Link to comment

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

  • Advertisement