Search Unity

Performance impact of attaching the same monobehaviours to multiple gameobjects

Discussion in 'Scripting' started by Zaine7673, Mar 28, 2021.

  1. Zaine7673

    Zaine7673

    Joined:
    Feb 15, 2018
    Posts:
    238
    I know the title is a bit vague but I didn't know how to put it into a single sentence.

    So what I'm wondering is if I have a monobehevaiour script that for example has a method defined with some logic in it.

    Then there is also a onTriggerEnter() checking for collisions and calls the method if the conditions are met.

    Let's attach this script to 10 gameobjects.

    I'm wondering if it is better for performance to separate the two sections into two separate scripts or if it doesn't matter. I'm not understanding if the method will be defined 10 times (as it is attached to 10 gameobjects) or just once.

    Sounds like a noob question but I'm just trying to gain an understanding of how this works.

    Would appreciate if someone could explain it.

    Thanks,
     
  2. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,605
    The methods are only defined once, but get called once per, well, call. There is also a slight overhead of having Monobehavior-Updates being managed by Unity, so over large quantities of objects it can be better to implement your own manager script which calls a custom Update function of the managed objects. However, for 10 or a couple douzen objects and scripts, none of this matters.

    For anything practical: only start optimizing once you profile an actual performance problem. Chances are you will otherwise spend a lot of time optimizing things that would have never become a problem. This rule of thumb holds true unless you are implementing something of which you know that performance is highly important (like a volumetric shader, or procedural landscape generation).
     
  3. Zaine7673

    Zaine7673

    Joined:
    Feb 15, 2018
    Posts:
    238
    Thank you clarifying this. I usually only use Update() for player input and player movements and so on. I was just curious about this as I am trying to implement a collectibles system. The easiest approach is to attach a script to each item to collect with an OnTrigger that detects if the player is near the Item. If the player presses a button then some method from another class is called. This class will manage the rest. The Script attached to the Item has some logic that defines the different types of items and their properties. having it on this script means that its all on one script and easier to manage. Then, for each gameobject, from the inspector I simply choose what item it is from an enum. My concern is that defining all of these items and their properties in this script may have an effect on performance once the number of items get into the hundreds. The items and properties only need to be defined once of course. I can easily move this to another script but then I'll end up with one extra script to manage when it comes to collectibles. From what you said, it seems that these items and properties will NOT be defined multiple times so should have no impact on performance?

    And Thank you again for the advice, I intend not to start going crazy with optimisation yet but I just want an understanding of how it works so I have the knowledge if I ever need it :)
     
  4. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,605
    Im not entirely sure i understand your approach. You intend to have all the code required for all items in one script? The size of the script would not impact performance in any meaningful way, but it would get harder to maintain. Thats what we usually use inheritance for.
    So you could have an abstract base class "CollectableItem", which would handle all the common functionality collectable items have. Then there may be a sub category of collectable items that can be used, such as potions or maybe some spell scrolls. So you could create another class inheriting from CollectableItem, called UsableItem, providing among others the "Use()" method. Something like a Potion could now implement the UsableItem class and implement or overwrite the Use() function with its own specific contents, ie healing the player. It would be both, type CollectableItem and type UsableItem. (This is just an example. If there were, for example, UsableItems that were not also CollectableItems, you would likely make one of the two or both interfaces instead.)

    But now youd have types classifying your items. I would make it so that the player detects items around him (not the items detecting the player). So you would check for collisions (or even better use a raycast), and then you can simply check if the other item has a CollectableItem script, if so, pick it up and put it into your inventory. Optionally you could make a quick check if its a UsableItem instead, and if so put it into a different inventory. When wanting to use an item, you dont need to know what item specifically it is, but instead you just need to call the Use function on any given UsableItem. Along a similar line of thought, you can handle interactable items in the scene the same way. A door, a light, a rope or whatever else, may all have their own way to interact with them, but the player only has to check if whats in front of him is an InteractableItem, and if so can simply call other.Interact().

    To answer your main question tho, a very long script will have no realistic impact on performance. Method and class definitions (in C#) only exist once at a special location in memory. What gets duplicated per instance are member variables of the class, ie some things like health, name, .. and so on. Since those need to exist once per instance in order to remember all the different values. If something is not needed per instance, you can make it const or static, in which case only one such value will exist in memory (but of course you cant have one value per instance anymore).