0
\$\begingroup\$

I used to create games from scratch with C++. There, people would create a "class Bullet", and add functionality to that class so that we can instantiate objects of class Bullet at runtime.

However, in Unity (which I'm new to), we need to create a Bullet GameObject in the editor, and then assign "class BulletBehaviourA : MonoBehaviour" to the Bullet GameObject. I don't really grasp this logic. Why don't we have a class for the Bullet in Unity?

\$\endgroup\$
3
\$\begingroup\$

Unity follows a principle called Composition over Inheritance.

When you have multiple entities in the game which have some behaviours in common and other behaviours which are unique to them, then there are three possible options:

  • One stand-alone class for each entity type. But if you have multiple entity types in your game which all move n pixels forward per tick, you have to write that movement code in every single one. So you will end up with lots and lots of duplicate code. This can become a lot of work to write and really difficult to maintain.
  • Inheritance. Extract common behavior into a common base-class and let every class that share this behavior inherit from it. So in this case you would create an abstract base-class Mover and every class which is supposed to share that behavior inherits from it. But if you use inheritance a lot, then you can encounter lots of design problems. For example, there is no good solution for multiple inheritance if multiple base-classes have a method with the same name. You can also end up with really confusing and unintuitive inheritance chains. This post-mortem of Starcraft 1 includes a paragraph "Game engine architecture" which shows just what a mess you can end up with if you follow the inheritance principle without taking the time to constantly review and refactor your class hierarchy. They ended up with an inheritance chain CUnit < CDoodad < CFlingy < CThingy with each of these things being something that could be instantiated and appear as an entity in the game world. What is the difference between a "Doodad", a "Flingy" and a "Thingy" you ask? Well, someone at some point certainly had a pretty solid idea of the distinction. Perhaps. Or not. If they had, they no longer remember.
  • Composition. Each entity is a collection of components. Each component is a class which implements one feature of the entity. You can add any component to any entity, so you can mix and match them at will. Unity also follows this principle. Note that the MonoBehaviours you create are not the only component on a game object. It always has at least a Transform and often a Collider, Rigidbody, MeshRenderer, MeshFilter and many more. These all implement features of your Bullet entity which your BulletBehaviourA class doesn't need to care about (unless it explicitly interacts with these components). By the way, having a component BulletBehaviour is often not the recommended solution in Unity. Usually you would break down all the things a bullet does into reusable components you can also use on other objects. In case of a Bullet, that could be

    • a MoveForward component, which you could reuse for anything that moves forward with a constant velocity.
    • a DamageOnImpact component, which you can put on anything which is supposed to remove hit points from any object it comes into contact with and has a HitPoints component.
    • a DestroyOnImpact component, which you can put on anything which is supposed to disapper after it comes into contact with something.

    If you add all three components to a gameObject, then you have a complete bullet. And what if you want to test how your game would play if bullets also had hit points? Easy. You just add the HitPoints component to the Bullet prefab and suddenly all bullets have hit points. Or you want a bullet which doesn't do damage but stuns enemies? Replace the DamageOnImpact with StunOnImpact for that one bullet. Or a bullet which seeks targets? Replace MoveForward with MoveTowardsClosestEnemy. Bullet that explodes? Bullet that shoots smaller bullets? All very easy and non-destructive experiments you can do in a composition-over-inheritance architecture.


Which one of these solutions is the superior one? That's a matter of personal opinion. But Unity has chosen the third option of componsition over inheritance.

| improve this answer | |
\$\endgroup\$
  • 2
    \$\begingroup\$ @xcrypt As I said, you would not have a class Bullet, you would have multiple classes inheriting from MonoBehaviour which each implement the different things a bullet does and then assign those classes to the Bullet prefab as separate components. \$\endgroup\$ – Philipp May 29 at 12:41
  • 2
    \$\begingroup\$ @xcrypt it's really not weird. Building a traditional class hierarchy went out of vogue a long time ago, for very good reasons. I suggest reading up on "entity component system" architecture. There are some pretty substantial design and performance advantages to be had just by changing your thinking a little bit. \$\endgroup\$ – 3Dave May 29 at 21:45
  • 1
    \$\begingroup\$ @xcrypt ECS is proven and tested. Disclaimer: I work for Unity. My friends at Epic (it's a very small world) agree with this. There are numerous issues with a strict hierarchy that are well-documented and have, in some cases, caused studios to crater because they couldn't pivot and adopt a more flexible architecture. ECS isn't new. It's just different, and has analogs that have been used in adjacent fields for decades. \$\endgroup\$ – 3Dave May 29 at 23:16
  • 1
    \$\begingroup\$ @xcrypt if you don't care about performance, flexibility or maintenance, keep going the way you are. \$\endgroup\$ – 3Dave May 29 at 23:18
  • 1
    \$\begingroup\$ @xcrypt The "default way" was never used by Id, among other studios. It didn't stop working - it came with inherent issues when OOP was misapplied. Punch cards worked for decades. Do you think we should still be using those? C++ performance is a result of the tools, not the language itself. Also, there's nothing about C++ that encourages or requires the type of hierarchy you to which you seem to be so attached. If you want to wind up with a 30k+ LoC "god class," have fun. \$\endgroup\$ – 3Dave May 29 at 23:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.