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. Dismiss Notice

Question Best Practices for instances of Components in custom Components

Discussion in 'Scripting' started by boabophone, Aug 21, 2023.

  1. boabophone

    boabophone

    Joined:
    Feb 23, 2021
    Posts:
    2
    Hi,

    First of all im new to Unity - so this might be a dumb question.

    Im struggling to understand if its better when making custom Components that use other Components, is it better to have an instance created via the UI and call GetComponent or is better to create new instance inside the script. Below is an example of what i mean:


    public class Controller : MonoBehaviour
    {
    private Rigidbody2D rigid_body = null;

    void Start()
    {

    // 1. Gets from instance added via UI
    this.rigid_body = this.GetComponent<Rigidbody2D>();

    // 2. Creates new instance and adds via script
    this.rigid_body = this.AddComponent<Rigidbody2D>();
    }
    }


    In my head its safer to use example 2 because it guarantees when the object Rigidbody2D will always be present and doesnt require creating other components per object if im reusing the Controller component.

    However most examples ive seen use example 1 and it does have the benefit of being more controllable prior to the startup of the system.

    I can see arguments for both, but id prefer to use the best practices cause they are usually there for a reason and like I said im new to Unity.

    Thanks for advice in advance :+1:
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,563
    It's tough... I do both, ALL the time.

    You can complexify it more by checking and only getting if null (I do this in a lot of stuff too)

    And you can make things ticklish if OTHER objects reach into here because of order-of-execution issues.

    So yeah, generally avoid ADD or GET as much as you can, but if it feels slicker then do it, but remember what you have done and where that Component ultimately comes from.

    This diagram can also help you reason about startup edge cases:

    https://docs.unity3d.com/Manual/ExecutionOrder.html
     
  3. wideeyenow_unity

    wideeyenow_unity

    Joined:
    Oct 7, 2020
    Posts:
    728
    This is for if there already is a Rigidbody component on the gameObject, as it "Gets" it.

    This is assuming that the gameObject in question does not have a Rigidbody component, and "Adds" one.

    As far as speed or performance, I would imagine the "Get" being slightly faster, since its copy already exists. And for the most part, most cases where you have a Rigidbody on something you want it to always be there, as you can play with the setting in the Inspector.

    If you only had it added after the game ran, you'd only be able to play with modifications while it runs, then save settings within the code later. So as Kurt mentioned, it's kinda just how you want to have it setup.
     
  4. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    20,082
    There's a third option: do it at design time.
    Code (csharp):
    1. [SerializeField, HideInInspector] private Rigidbody2D rb;
    2.  
    3. void OnValidate()
    4. {
    5.     rb = GetComponent<Rigidbody2D>();
    6.     if (rb == null) rb = AddComponent<Rigidbody2D>();
    7. }
    https://docs.unity3d.com/ScriptReference/MonoBehaviour.OnValidate.html
     
    CodeSmile and Kurt-Dekker like this.
  5. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,563
    I like that option ^ ^ ^ ^ better than the RequireComponentAttribute

    Yours lets you preload settings upon "Add"... nice!
     
  6. boabophone

    boabophone

    Joined:
    Feb 23, 2021
    Posts:
    2
    Hi All,

    Thanks for the responses its really helpful!

    Its interesting to see there isnt a general consensus - im used to rigid rules and datasheets - very cool to see how flexible this is and that even experienced users do things differently.

    Just a bit more context im far far away from optimisation needs at the moment, i generally always optimise later and keep it simple to start with.

    I think like ill be copying this snippet everywhere - having a default is perfect

    Thank you all again for the input and quick responses - great community!
     
    Kurt-Dekker likes this.
  7. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    3,899
    [RequireComponent(typeof(Rigidbody2D))]

    Put this above the component class. This guarantees that the rigidbody component exists but only if you have this attribute on the script before adding it to a game object. Unless you need preset default values other than Unity‘s default values this should be the go-to solution.

    Otherwise the OnValidate version is preferable, or if you already added your component to many prefabs (but I‘d still add the RequireComponent attribute regardless).

    The good thing about RequireComponent is that you see the requirement in code spelled out explicitly at the top and the Inspector prevents users from removing the required component(s). The downside is, if you have a require component chain it can be annoying having to remove components in a given (possibly unknown) order in the Inspector.