You want each component to dedicate to a single and simple task. You want each component to just operate on a single problem domain. You want them to be as independent and self-sufficient as possible, and at the same time you want to design them in a way that lets you place them together seamlessly to work for a higher cause. The benefits of designing components like this are pretty obvious. They can be added, removed, changed or tweaked without causing much trouble to other components around them, if at all.
However, there's still an important aspect about them: Some of them talk. Some of them listen. Some say things about interesting events happening to them and some listen to these events and do interesting things in turn; or they simply ask other components to do something for them. What does this mean? If they communicate, they must use some kind of channel to do so. In 99% of the examples on the internet, this channel is a specific method call made to a specific component, found by any of the GetComponent() family of methods. This means that the caller has to know about the recipient's components. This means that a programmer has to know what components a level designer has put within the GameObject, thus creating not only a dependency in source code, but an inter-departmental dependency! Well, this is pure evil and actually defeats the whole purpose of the component-based model itself. There's a reason you design your classes using abstraction and encapsulation. Why wouldn't you do the same with your components?
So, how do we communicate to other components then? Through messaging. Messaging provides us a decoupled channel for communication. The responsibility of the sender is just to send a message through the proper channel. Sender does not need to know about the recipient's identity. Likewise, the responsibility of the recipient is to subscribe to the messages it wants to handle, without knowing about the sender identity.
Unity's Monobehavior does, in fact, support a half baked way to communicate to other components through messaging, but it's not to be trusted. It uses reflection which means it's incredibly slow. Yes, it's incredibly slow. If you go the messaging way, you'd be using messages for everything. Don't buy the "Ok, it's slow but it's meant to be used just here and there" argument. There's also strange methods like "SendMessageUpwards" which basically invites you to create a dependency within the lovingly-crafted-by-a-level-designer object hierarchy.
I honestly think Unity 3D has no real support for messaging, and out of the box, it's certainly near to impossible to take advantage of the many cool features that real component-based systems offer. That's why I decided to write this lightweight framework called "The Guay Framework".
I'll write more about this in future posts.
No comments :