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

FeatureRequest: AddComponent with initial enabled state.

Discussion in 'Scripting' started by koirat, Oct 3, 2019.

  1. koirat

    koirat

    Joined:
    Jul 7, 2012
    Posts:
    2,008
    Hello.
    I'm working with unity since almost the beginning and some missing features comes back to me quite often.
    One of them is the ability to AddComponent with it's initial Enabled state.

    I'm talking about something like this AddComponent(Type type,bool enabled).
    By setting enabled to false component would be added disabled and without OnEnabled called.

    It would be super useful, especially when crating your GameObjects at run-time.

    Right now there is no clean/proper solution for setting fields that are used in Awake and OnEnabled to just added component.
     
    AltIvan, kotoezh, ebaender and 2 others like this.
  2. MadeFromPolygons

    MadeFromPolygons

    Joined:
    Oct 5, 2013
    Posts:
    3,875
    I dont think they need to add further bloat to the engine to reduce a single line of code?

    You can achieve this by doing the following:

    Code (CSharp):
    1.  ComponentType com = gameObject.AddComponent<ComponentType>();
    2. com.enabled = false; // all you would be removing is this single line of code
    You can also access the fields etc in there and set them up. If you need more control over awake and start, dont use them and instead create your own Setup method that you call such as:

    Code (CSharp):
    1. com.Setup( value1, value2, value3 etc);
    You can also craft the objects at runtime using a prefab or scriptable object as a template. We use scriptable objects in our game object spawning scripts to allow us to provide the fields we want it to have at start. Lots of ways using the already existing API to do this, and they are all easily generalisable meaning you can write it once and use it on lots of stuff in every future project. Just wrap up your spawning logic inside a method that you can pass stuff into and create a setup method like I mention above and you wont need to write this again.

    Good luck! :)
     
  3. koirat

    koirat

    Joined:
    Jul 7, 2012
    Posts:
    2,008
    If it was only so simple as additional line of code I would not create the topic for it, I would create an extension method.

    And no it would not be like removing this simple line of code.

    To put it simple you cannot add new component to active gameobject without invoking it's OnEnable and when you disable gameobject to achieve such a functionality (disable GO, add component disable component, and than activate object again) you will invoke OnDisable on other already added components.

    Also why should I go to the extent of creating additional functions like "setup" {btw. this would be what I would call bloat} when I already got all in place, I just need to be able to add disabled component.

    Secondly unity is actually having such a functionality, since you can instantiate prefab with disabled components. So why not allow user to do it.
     
    Peymann, kotoezh, lordofduct and 2 others like this.
  4. okluckej_unity

    okluckej_unity

    Joined:
    Aug 30, 2020
    Posts:
    11
    Hi,

    definitely agree with you koirat. In current state you have basically 3 solutions.
    1. Disable game object, add component, do some proper initialization and enable game object
      1. This has some major drawback like executing OnEnable/OnDisable on other behaviors
    2. Do not rely on Awake, Start, OnEnable to get data from initialization
    3. Disable the component in Awake.
      1. Requires little coding in every component, forces Awake to be implemented. Put another stuff to remember on programmer
    All solutions are kinda clunky and would be nice to have a proper solution to enable manual initialization without hacking it.

    Code (CSharp):
    1. public static MonoBehaviour InitializeComponent<T>(this GameObject gameObject) : where T : MonoBehaviour, IInitializableMonobehaviour
    2. {
    3.     object payload = CreatePayload(typeof(IInitializableMonobehaviour));
    4.     IInitializableMonobehaviour iim = gameObject.AddComponent<IInitializableMonobehaviour>(false);
    5.     iim.Initialize(payload);
    6.     iim.enabled = true;
    7.     return iim;
    8. }
     
  5. Spykill

    Spykill

    Joined:
    Jul 10, 2014
    Posts:
    1
    I would very much support this. Having components that register and unregister OnEnable/OnDisable is incredibly clean from a component perspective, but it becomes significantly less clean when registering requires variables to be assigned beforehand.

    While all these other solutions could work, they make it much more difficult to have components in the scene enable by default, while having spawned components wait to be populated.

    Having an optional "enabled" parameter to AddComponent would solve this and seems like the cleanest solution out of all to me.
     
  6. LazloBonin

    LazloBonin

    Joined:
    Mar 6, 2015
    Posts:
    795
    I google for this and land on this thread every few months.

    I think this is the single thing that would most improve my entire codebase.

    Praying that anyone from Unity sees this!
     
  7. thomasvaniseghemSB

    thomasvaniseghemSB

    Joined:
    Sep 15, 2022
    Posts:
    12
    Would like this feature also. I'm having trouble creating components and having them call OnEnable without having a chance to set the parameters first. I can call myClass.OnEnable manually and everything works, but my console is spammed with error messages from the first attempt. Having a try catch in the OnEnable would also be a bit clunky.
     
  8. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    5,848
    You could just have a
    private bool isInitialised;
    that your OnEnable checks.

    Though honestly this is just a situation where you should just be introducing your own
    Initialise()
    method and calling that, rather than using Unity's callback in this situation.
     
  9. ThisIsNik

    ThisIsNik

    Joined:
    Oct 28, 2019
    Posts:
    9
    I'd love this feature as well. It would be really useful for code reuse. A project could choose to either assign inspector fields through editor or add component at runtime and Construct() with required fields.
     
    Last edited: Jul 11, 2023