Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

OOP/Unity design question - Inheriting Monobehaviour

Discussion in 'Scripting' started by blingle, Apr 30, 2020.

  1. blingle

    blingle

    Joined:
    Apr 12, 2020
    Posts:
    17
    (Old hand at procedural, new to OOP/C#)

    I have a box prefab.
    When it gets instantiated I want to change its colour and assign it some "content". I can easily do this in a custom class that's not derived from `MonoBehaviour`.

    However it seems Unity requires any attached script component to be derived from MonoBehaviour.

    So my question is - do I inherit from MonoBehaviour even though I don't need any of its components for this just so I can assign the script component? Seems like there's be a potential performance hit (there may be thousands of these boxes in a scene!).
    Or do I do it the other way around and assign the Box GameObject to a class variable manually during instantiation and keep it a custom class?
    (Or something else?) What's considered best practice?
    Thanks
     
  2. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,590
    If you need to attach a script as a component to a gameobject, then it has to derive from Monobehavior.

    If you want to change a color or assign some other settings to an Instantiated() cube, then this should most likely be done by the script which does the instantiation. Since the function doing this is already called from somewhere, i'm not entirely sure i follow your problem. Do you want to attach the script which does the color chaging to the cube itself? If so, you need it to be Monobehavior anyways, since otherwise you couldnt execute your code once the object was instantiated (which is handled by, for example, Start()).
     
  3. blingle

    blingle

    Joined:
    Apr 12, 2020
    Posts:
    17
    Thanks @Yoreki - I'm probably just over-thinking it while I try and grok what's going on.
     
  4. Vryken

    Vryken

    Joined:
    Jan 23, 2018
    Posts:
    2,106
    You can actually inherit parent classes of MonoBehaviour if you just need to attach your script to a GameObject, but you don't need any MonoBehaviour features.

    MonoBehaviour inherits from Behaviour, which inherits from Component.

    In a nutshell:
    • MonoBehavours are Components that receive Unity callbacks, such as
      Awake
      ,
      Start
      ,
      Update
      ,
      OnEnable
      ,
      OnDisable
      , etc.
    • Behavours are Components that can be enabled/disabled.
    • Component is the base class for all scripts that can be attached onto GameObjects.
     
    PraetorBlue likes this.
  5. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,385
    You'll be able to inherit in C#, but you won't be able to attach it to a GameObject or run it in Unity.

    If you do you'll get a compiler error from Unity (not from Visual Studio) like this:
    upload_2020-4-30_15-53-6.png
    (got a screen shot as well)

    This error description implies that Unity intends only classes that have a native counterpart to inherit from Component or Behaviour directly. Like Collider and Transform have native side implementations.

    This isn't to say those classes are useless though, and can come in handy for any polymorphic methods you write that want to take in both MonoBehaviour based scripts and unity specific ones like Transform/Collider/etc which don't inherit from MonoBehaviour.
     
    Joe-Censored and PraetorBlue like this.
  6. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    You might consider creating a single Box manager script which maintains and manages all this Box "content", etc, as well as references to the boxes. That likely performs better than a few thousand MonoBehaviour instances.

    Though if you're talking about thousands of prefab instances in the scene, you may end up with unacceptable performance regardless, depending on your target platform. You're approaching DOTS/ECS territory, so maybe you should look into how that new system works.
     
  7. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    1,926
    A working non-attached script is fine, and looks like this:
    Code (CSharp):
    1. class BoxChanger {
    2.   public Transform b;
    3.  
    4.   public becomeRed() { b.GetComponent<Renderer>().material.color=red;
    5. }
    6.  
    7. BoxChanger box1 = new Box1();
    8. box1.b = Instantiate(boxPrefab);
    9. box1.becomeRed();
    It's a tiny bit more work than a monobehaviour (requires 2 Instantiates instead of 1), but a tad more lightweight. The main drawback is if you sometimes find those gameObjects by raycasts or collisions. Suppose in either case you have lots of them, in an array. With a monobehavior,
    go.GetComponent<BoxChanger>()
    is all you need to find the script, which can hold the index. With a normal class, you'll need to search your array for the one with the matching gameObject. But then again, that's one line and fast enough. Both ways are pretty much the same.