Unity – Keeping objects modular WITHOUT SendMessage

An earlier post of mine explained how Unity’s built-in SendMessage() method could be used to help write highly modular components.

However, there are some major disadvantages to SendMessage. One is that it can easily lead to errors that can only be detected at runtime and can be difficult to find. This is because the method to be invoked is passed in to SendMessage as a string, so there is no guarantee that the receiving object has a method with the same name. Unity will print an error if this happens, but only if it actually happens while the game is running in the editor. The other big problem is that SendMessage is slow. Very slow. The general consensus is that sending a message with SendMessage is about 10 times slower than calling a method on the object directly. And it’s even slower on iOS, possibly as much as 100 times slower than a direct call. This makes sense, because SendMessage must use reflection to look up the names of all the methods on all the components on the target object, perform string comparisons, and then invoke the methods on the resulting set of objects.

So SendMessage is slow. What’s the fast way?

Probably the quickest and most elegant design is to create either a base class or interface for components you want to have receive messages, and create virtual methods for each of the messages you’ll send. If you want most or all of your components to be able to receive messages, it might make sense to extend Unity’s base MonoBehavior class with your own methods.

public abstract class MyBaseGameComponent : MonoBehavior
{
     public virtual void OnUse(Player user) { }
     public virtual void OnHitByBullet(Bullet bullet) { }
}

A child class can then extend MyBaseGameComponent and be sent messages by normal method calls.
This technique requires a bit more planning, as you need to know what messages you want to send, but it also helps the speed problem dramatically (virtual methods calls have some overhead, but nowhere near as much as SendMessage). Plus, the compiler/IDE will give us an error message if we try to invoke a method that doesn’t exist. Not bad!

Advertisements

Tags: , ,

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: