28

MonoBehaviour extends Behaviour and Behaviour extends Component. I want to know why these classes are separated and the semantic meanings of these classes. Is there any purpose to separate these classes? And are there any classes extending Behaviour or Component directly?

I know we must use MonoBehaviour to create C# code in Unity. However, I'm interesting in architecture of Unity as a game engine.

starball
  • 20,030
  • 7
  • 43
  • 238
kyasbal
  • 1,132
  • 3
  • 12
  • 27
  • 3
    You don't need to inherit MonoBehaviour if you're not writing code that will be `Start`ed and `Update`d – Dmitry Pavlushin Jun 14 '17 at 09:30
  • 1
    @DmitryPavlushin hey, this is interesting, can we inherit from Behaviour or Component in the case we don't need `Start` or `Update`? I personnaly try to avoid using these (I prefer event-driven code when it's possible), so if we can inherit those, can it be a better practice? – Alex Ferretti Jun 14 '17 at 09:57
  • 1
    @DmitryPavlushin sounds like an answer. – vikingsteve Jun 14 '17 at 10:00
  • Let's take an example, you may have a prefab for instance containing data about the prefab on a MB script. When creating the new instance via the prefab you access those data and run some method on it. You access the script via GetComponent. Regularly in the game you need to access those data because let's say your item is a projectile damaging other items. The script may not have any Start nor Update. For this reason the first comment is wrong. – Everts Jun 14 '17 at 11:31

1 Answers1

32

Component:

Component is a base class for both Behaviour and MonoBehaviour. It is a base class of any script that can be attached to a GameObject.

This is what almost every Unity build-in script derives from. This includes Collider and Rigidbody.


Behaviour:

The most important thing to know about Behaviour is that anything that inherits from it can be enabled or disabled. Do not inherit your script from this if you don't want it to be enabled/disabled.

For example, Rigidbody cannot be enabled/disabled. This is why it inherits from the Component class instead of Behaviour.

Behaviour inherits from Component.


MonoBehaviour:

The most important thing to note about MonoBehaviour is that you need it when you have to use coroutines, Invoking, or any Unity callback functions such as physics OnCollisionEnter function, Start, OnEnable, OnDisable, etc.

MonoBehaviour inherits from Behaviour so that your scripts can be enabled/disabled.

Are there any purpose to separate these classes?

Yes, like the answer above, they are separated so that you can use different features by inheriting from the appropriate component.

You want coroutine, Invoke, InvokeRepeating and be able to enable/disable your script? Use inherits from MonoBehaviour.

You want to be able to enable or disable your script but don't need coroutine, Invoke, InvokeRepeating? Use Behaviour.

When you have a scripts that should never be enabled/disabled, that should inherit from Component.

Note that Behaviour and Component are used by Unity for internal stuff. You should not try to inherit your script from these.

The main reason for separating these is to conserve memory and also make the code in each component easy to maintain. This is better than writing thousands of lines of code for a feature that one rarely use. By separating them and when they are loaded into the memory they are actually being used and not wasting space in the memory.

And are there any classes extending Behaviour or Component directly?

Yes.

  • MonoBehaviour inherits directly from Behaviour which then inherits from Component.

  • Collider inherits from Component directly. Then non base colliders such as BoxCollider and SphereCollider inherits from that Collider.

starball
  • 20,030
  • 7
  • 43
  • 238
Programmer
  • 121,791
  • 22
  • 236
  • 328
  • So, is inheriting MonoBehaviour when we don't need the unity callback function a bad practice? – Alex Ferretti Jun 14 '17 at 10:03
  • Yes, it takes so much memory that will only be free when next scene is loaded. The `Destroy` function does not actually destroy objects. It simply marks as deleted. It is worse than leaving empty `Update` function in your scripts. – Programmer Jun 14 '17 at 10:09
  • It's not about making non MB when not needing the Update. It is about whether you need your class to take advantage of what the engine offers. Else you could have one MB and the rest gets called from it but it would make things more complex. Say your class needs some GO references or you need to access it via another object or else. Those cases are easier with MB. – Everts Jun 14 '17 at 11:26
  • 1
    @Programmer "Yes, it takes so much memory that will only be free when next scene is loaded. " you sure of that? It will remain until end of the frame then it is marked for GC. If a scene load would be required to clean up destroyed objects, it would be a major drawback on the design. Or did you mean different? – Everts Jun 14 '17 at 11:37
  • I did not only mention the `Update` function. I also mentioned coroutines, Invoking, Unity callback functions and being able to enable/disable the script. All these fall into advantage of what the engine offers. *"Else you could have one MB and the rest gets called from it but it would make things more complex"* You don't understand my statement. I've seen many people make all their script `MonoBehaviour` because they think it is necessary. It's not. For example, attaching 10 scripts to one GameObject with each script inheriting from `MonoBehaviour` is costly. – Programmer Jun 14 '17 at 11:45
  • One script with `MonoBehaviour` is enough. The other scripts can be used as composition inside that one `MonoBehaviour` script for each Object if they don't need those features I mentioned above. Don't even forget that you [can use coroutine](https://stackoverflow.com/a/40509118/3785314) in a class does not inherit from `MonoBehaviour`. This will save you so much memory on low end mobile/Android devices. – Programmer Jun 14 '17 at 11:50
  • Glad to read this! I also always used `MonoBehaviour` classes because of the "It works so let's keep it like this" way of thinking :) I guess I'll have to test this myself ("Only believe what you've seen") but definitely trying to save some memory here and there! – Kardux Jun 14 '17 at 12:05
  • Anyway, what is the meaning of 'Mono' of 'MonoBehaviour'? Is that same semantic of Mono of MonoDevelop? – kyasbal Jun 14 '17 at 12:42
  • @Everts "If a scene load would be required to clean up destroyed objects, it would be a major drawback on the design. Or did you mean different?"* I meant exactly what I said. `MonoBehaviour` inherits from `UnityEngine.Object` and that has nothing to do with Mono. Last time we did a test on this, we found this. Now, I can't tell if that was a memory leak bug or just by design but it goes away when scene restarts. It seems to happen to anything that inherits from `UnityEngine.Object`. This was long ago. I will do a test this weekend and report back to you about this comment. – Programmer Jun 14 '17 at 13:01
  • @kyasbal Sorry. I don't work for Unity and can't speculate on that. – Programmer Jun 14 '17 at 14:26
  • 1
    @kyasbal could be historical reasons due to the underlying Mono framework. Just like all Objective-C class starts with NS when it was NextStep. Then it would be too complex to remove the prefix while it does no harm. – Everts Jun 15 '17 at 13:38
  • 4
    "Note that Behaviour and Component are used by Unity for internal stuff. You should not try to inherit your script from these." This some contradictory to everything else you've said. When I read that, it sounds like you say to never inherit from Behaviour or Component. Is that what you mean? – Evorlor Sep 18 '17 at 18:31
  • 1
    @Evorlor Yes, that's what I meant. Never inherit from them. If this changes I will update my answer. – Programmer Sep 18 '17 at 19:50
  • 1
    I am confused, then. Doesn't that contradict this: "When you have a scripts that should never be enabled/disabled, that should inherit from Component." – Evorlor Sep 18 '17 at 19:52
  • 2
    I know that's confusing but when I say "you", I don't mean a normal programmer like you. I'm mainly referring to programmers that work for Unity. I am also referring to programmers that contribute to [Unity's UI system](https://bitbucket.org/Unity-Technologies/ui) which is open source. You will have to understand how these work, why they are used and when to use any of them in order to make a contribution. If you are not any of these people, you don't need to use any of these. – Programmer Sep 18 '17 at 20:10
  • Ah, gotcha. Thank you. So let's say I have a component where I strictly store data attached to a GameObject. I should inherit from MonoBehaviour, opposed to Component? – Evorlor Sep 18 '17 at 20:16
  • Like I said, you should never inherit from `Component` or `Behaviour` unless you are modifying/contributing to core Unity API. If you are just using a script to store data only then don't inherit from any of these or from anything at-all. In this case, it would be easier to serialize(json or binary) your data so that you can save it and load it next time. See the `PlayerInfo` class from [this](https://stackoverflow.com/questions/40965645/what-is-the-best-way-to-save-game-state/40966346#40966346) post for example of what I am saying. – Programmer Sep 18 '17 at 20:25
  • Thanks for the tips! And sometimes it is beneficial to store data as a Component. Specifically so that you can change the values from the inspector on the fly. – Evorlor Sep 18 '17 at 20:35
  • 2
    No, you don't have to store it as Component. As soon as you declare that data class inside another class you created from MonoBehaviour, you will see that data class in the Editor/Inspector with all of it's variable. They have to be declared as public and or must have `[SerializeField]` if private. – Programmer Sep 18 '17 at 20:44