*** EDIT: I’ve decided to release this with full source for anyone who wants it
Message Bus With Source - FREE DOWNLOAD
I’m still working on some sample projects but haven’t had the time to complete them yet. In the meantime I’ve decided to offer up the message bus free of charge, both the compiled binaries and the full source code (Visual Studio 2010 / 2012 projects / solution) with unit tests. The solution should also open fine in MonoDevelop.
Two things to note:
-
When opening the source in VS / MonoDevelop - you will need to re-add the reference to UnityEngine.dll to the DH.Messaging.Extensions project. I wasn’t sure what the redistribution policies were for UnityEngine.dll so I did not include it in the zip file.
-
Currently no serialization attributes exist for any of the MessageBus classes. If you needed to serialize messaging you’d need to implement that in the provided source and recompile.
Here’s the link to download:
http://unity.dustinhorne.com/downloads/messagebusv1.zip
and here’s the technical documentation link again:
http://unity.dustinhorne.com/documentation/messaging
Feel free to PM me with any questions or if you need help setting it up.
*** ORIGINAL POST ***
Hello team! I’m working on a new asset that I’m going to be submitting to the Asset Store and I would like to solicit two things from you guys and below these questions is information about the asset:
-
How much should it cost? Free isn’t an option at the moment but I don’t want to gouge people either.
-
What do you think of the Asset and Implementation? This is really the important question. I need to know if you think the features are useful and what if any additional features you’d like to see.
Documentation (link is also at the end of the post)
http://unity.dustinhorne.com/documentation/messaging/
What Is It?
It’s a messaging system for Unity3D. There are two main pieces in the system. The first is a first-come-first-serve message pool. The second is a message bus that objects can subscribe to. It’s written in C# (Visual Studio 2012) and compiled to a single assembly. It works with both Unity Free and Unity Pro. The code has already been written and pretty heavily tested, but may change based on feedback here.
The Message Pool
The message pool is meant for registering simple messages and retrieving them with your components. The first component to grab the message removes it from the pool. This is useful if you want to just do something once for whoever might look for the message. As an example, you could have a piece of code that calls the static manager to add a message:
PoolManager.AddPoolMessage("SomeMessageKey", "I have arrived!");
You can add as many messages as you want to each key. Components looking for these messages will just grab them one at a time in the order they were added. Example:
string myMessage = PoolManager.GetNextMessage("SomeMessageKey");
The only requirement is that the message pool exists, which is done by calling:
//Create the pool with the default max size
PoolManager.CreatePool("SomeMessageKey");
//Or create the pool with a max message size
//Old messages will be truncated automatically to keep the pool size down.
PoolMaanger.CreatePool("SomeOtherKey", 500);
The Message Bus
The message bus itself is much more robust. It utilizes a subscriber model allowing individual components to subscribe to messages of a specific type and key. When messages are added to the message bus manager it looks for subscribers of that specific type and key combination and delivers the message to all subscribers. The “Message Key” is a way to allow multiple messages to be of the same type but have different meaning. Every “Type” specified for a message creates an internal message bus that handles all messages within it.
To work with the message bus, I created a component (MonoBehavior) that can be attached to any GameObject. This component (MessageBusSubscriber) handles all of the subscriptions for that game object. I also added some game object extension methods allowing you to create a default empty subscriber or you can subscribe to a specific message type. If you subscribe and the subscriber component doesn’t exist, one is automatically created for you. The subscription is automatically registered with the message bus and will start receiving messages. Here’s an example:
var subscriber = gameObject.SubscribeToMessage<Vector3>("PointOfInterest");
This code will automatically call AddComponent on the game object if the component doesn’t already exist. Furthermore, it subscribes to any message with the type of Vector3 and the key of “PointOfInterest”. The extension methods all return the MessageBusSubscriber instance (either existing or newly added) so you can perform additional options. To retrieve the MessageBusSubscriber you can call:
var subscriber = gameObject.GetComponent<MessageBusSubscriber>()
or use the extension method:
var subscriber = gameObject.GetSubscriber();
Now, we’ve subscribed to the Vector3 message with key of “PointOfInterest” above, but we want to set some additional properties on our subscriber:
var subscription = subscriber.GetSubscription<Vector3>();
Importantly, all Vector3 type messages are handled by the same subscription, regardless of the key. The subscriber let’s us configure when messages are processed (Update, FixedUpdate or LateUpdate). The MessageBusSubscriber component handles processing the messages at the appropriate time and will process all messages in an active subscription in a frame. If you’ve subscribed to multiple keys, multiple messages will be received and processed. By default, messages are processed during “Update” but we can now say:
subscription.UpdateType = UpdateType.FixedUpdate;
There are several options that can be configured. Now, to send a message, from any code we’re executing you can call:
MessageBusManager.AddMessage<Vector3>("PointOfInterest", new Vector3(1, 3, 3));
That message will be delivered to every subscriber of that type and key. Every subscriber will receive the Vector3 we supplied. Messages are generic and you can register and send any type of message you want.
On the subscription side, every “subscription” (not subscriber) has an OnMessageReceived event. This event is fired for every message that was processed during the given frame. The event gets two arguments… the a reference to the MessageBusSubscriber instance and a MessageReceivedEventArgs object. The arguments has (string) MessageKey and (T) Message properties.
You setup an event handler for every “Type” of message (not every key), then based on the key you can perform different actions from your handler. In this case your event handler will handle MessageReceivedEventArgs and the args variable will contain the “PointOfInterest” key and the Vector3 we supplied.
Why is this useful?
Being component driven, Unity allows the objects and components to access eachother in a variety of ways, such as finding objects by tag name and finding objects by id or just directly referencing objects. This system allows you to broadcast messages that will be received by anyone subscribing to that message regardless of tags or type of object. You can put your event handler logic in a prefab or script to attach. Here’s a good example:
Let’s say you have a crowd of characters. You want all characters to react to certain events. If it’s an Explosion, you want them to run away… if it’s a loud noise you want them to turn and look. The only thing they need to know is what the event was and what the location was. So, you create a script that does this:
var subscriber = gameObject.SubscribeToMessage<Vector3>("Explosion");
subscriber.SubscribeToMessage<Vector3>("LoudNoise");
var subscription = subscriber.GetSubscription<Vector3>();
subscription.OnMessageReceived += ReactToNoise;
and we setup our handler
public void ReactToNoise(MessageBusSubscriber s, MessageReceivedEventArgs<Vector3> args)
{
switch args.MessageKey
{
case "Explosion":
RunAway(args.Message);
break;
default:
LookToward(args.Message);
break;
}
}
Ok… this has gotten to be a much longer post than I anticipated. So, I’ve put together some preliminary technical documentation of the library. I’d love to hear what people think and what questions they have. I may also open it up for some very limited beta testing before I submit it.
Here’s the documentation:
http://unity.dustinhorne.com/documentation/messaging/