So, this post is as much for the world as it is to give me a chance to write things out to help me visualize things more clearly.
Rather than the traditional object-oriented design paradigm, Unity uses what is known as a component-based architecture. What does that mean? The common answer is that in object-oriented programming, objects have an X ‘is a’ Y relationship, whereas component-based architecture invokes a X ‘has a’ Y relationship. It means that instead of each object in Unity being the child of a child of a child, with the root class being the most generic category and each sub-class extending the functionality of it’s parent classes, objects in Unity start out as the most generic class, and then are given specific attributes, or components, which govern how they act. So where a ‘kitten’ object in an OOP setting might be implemented by this hierarchy:
Animal -> Four Legged -> Cat -> Kitten
that kitten in a component based architecture would be:
Cat : contains Generic Animal behavior, Four Legged behaviour, Cat behaviour, and Young Animal behaviour.
After learning OOP nearly exclusively in college, this can be a little hard to get your head around. I mean, it lacks a neat structure, and especially in Unity, where each GameObject would naturally map to one OOP object, it’s difficult to start thinking differently. For instance, it was frustrating to me, having only learned OOP, to try and organize my objects, since implementing GameObjects as a subclass of something else (such as making each zombie a subclass of a more general ‘enemy’ class) isn’t particularly easy to do, especially in UnityScript. Couple this with the fact that you’re not calling functions from the object, but calling functions from object.GetComponent(Y), and it starts to really look much different from what you learned in college.
However, for game programming especially, the component model makes a TON of sense, once you make the breakthrough and grasp the core abstract concept – instead of your objects behaving based on what they are, they behave based on what functionality they need. It’s much more a horizontal organization, and therefore harder to organize, but it makes a lot of sense when you have a lot of objects that share some features, but not others. For instance, imagine a real-time strategy game where you have ‘hero units’, with special powers and abilities. However, they still share the same base features as the regular units of their type. With OOP, you might have an entirely separate class structure, with lots of duplication of features, but with components, you take your existing soldier, swap out its weapon with the hero’s weapons, add in some special ability scripts, and boom, you’re there.
Another example: You have a FPS where you can blow stuff up. You have a zombie enemy that you want to apply damage to when it gets caught in an explosion. All enemies in your game should take damage, so you put the ApplyDamage function into the parent class ‘Enemies’. However, you want to implement boxes that get destroyed by explosions – do you move ApplyDamage up the hierarchy? By the time boxes and zombies have something in common, that’s pretty high up, like maybe a ‘PhysicalObjects’ class?. Meanwhile, you’ve also got an object, say a health pack you don’t want to be destructible – do you just give it infinite health points? Branch it off, so you have a ‘PhysicalObjects’ class with a ‘DestructibleObjects’ and ‘NondestructibleObjects’ classes?
What a mess.
With components, just have a ‘Destructable’ component, and give that component to any objects that you want to be destructible. Too easy.
It’s a big change, though. It means thinking about your objects in a way that seems totally backwards – instead of starting off with a super-general class and winding up with children objects that are super-specific, you start with a completely generic object and add in distinct bits that differentiate this object from every other one out there. It loses the strict organization that OOP has, but it does have a certain aesthetic – every object is defined exactly by what it needs to do. If an enemy is invincible, instead of a kludge where it has a million HP, or a special flag, the enemy just doesn’t get a ‘recieve damage’ script. If some boxes and barrels contain items, just give those ones a ‘contains item’ script.
Of course, I’m just figuring this stuff out, so it’s still fresh and exciting for me. It’s also something I never really had particularly explained to me with Unity – a lot of that is my fault; since the Unity introduction and tutorials are somewhat written for total beginners, with some programming background I wound up more or less skimming through without really internalizing what the component model meant. Still, it’s something that took a fair bit of searching on my own, and while object fundamentals are explained, there isn’t really a section that sits you down and says, ‘Hey, Object-Oriented Programmer, this is a significantly different paradigm!” I hope it helps anyone out there looking at getting into Unity!
