FeatureRequest: AddComponent with initial enabled state.

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.

8 Likes

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:

 ComponentType com = gameObject.AddComponent<ComponentType>();
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:

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! :slight_smile:

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.

8 Likes

Hi,

definitely agree with you koirat. In current state you have basically 3 solutions.

  • Disable game object, add component, do some proper initialization and enable game object

  • This has some major drawback like executing OnEnable/OnDisable on other behaviors

  • Do not rely on Awake, Start, OnEnable to get data from initialization

  • Disable the component in Awake.

  • 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.

public static MonoBehaviour InitializeComponent<T>(this GameObject gameObject) : where T : MonoBehaviour, IInitializableMonobehaviour
{
    object payload = CreatePayload(typeof(IInitializableMonobehaviour));
    IInitializableMonobehaviour iim = gameObject.AddComponent<IInitializableMonobehaviour>(false);
    iim.Initialize(payload);
    iim.enabled = true;
    return iim;
}
1 Like

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.

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!

3 Likes

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.

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.

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.

I’m really waiting for this

I do see that this thread is a few years old… but it’s been necroed a few times now so I’m just going to put my 2 cents in.

Whenever I needed anything like this I just disable the gameobject then enable it when it’s done.

This works regardless of of we’re instantiating a prefab or creating gameobjects and adding components.

var go = new GameObject("Test");
go.SetActive(false);
go.AddComponent<MyComponent>();
//build out our gameobject anymore that we want
go.SetActive(true); //here Awake/OnEnable will actually occur
prefab.SetActive(false);
var inst = Instantiate(prefab, pos, rot);
//do whatever is necessary before enabling
inst.SetActive(true);

Usually my object creation all occurs in some factory pattern and this just sort of inlines to that pattern.

If you’re adding a component after the fact well. Honestly I’ve never found myself in that scenario where I’m adding a component to an already active gameobject that’s been active for some time, that also needs some heavy lift initialization like this during Awake/OnEnable.

With that said… you can disable and reenable a gameobject without it flickering or anything. All your script code is running between frames. So it’ll be fine.

The only weird part would be that if any scripts on said GameObject perform an action during OnDisable this will cause it to happen and you might not want that. In which case you’ll have to go an extra step.

But like… this is REALLY edge case. And why can’t you just use ‘Start’ instead? Or setup an Initialize method or some factory method that works around it.

2 Likes

My solution to the problem:

I derive from generic base class to be able to receive arguments during initialization:

class MyComponent : MonoBehaviour<Value1, Value2, Value3>
{
    Value1 value1;
    Value2 value2;
    Value3 value3;

    protected override void Init(Value1 value1, Value2 value2, Value3 value3)
    {
        this.value1 = value1;
        this.value2 = value2;
        this.value3 = value3;
    }
}

Then I can use a generic extension method to initialize a component with arguments:

gameObject.AddComponent(out MyComponent myComponent, value1, value2, value3);

What happens behind the scenes is:

  • The AddComponent extension method temporarily stores the passed arguments in a static member, right before calling AddComponent().
  • The created component automatically retrieves the arguments via code in the base class at the beginning of its Awake event, and passes them to the Init method.

Being able to do this is really useful for unit tests, since usually you can’t pass anything into private serialized fields from the outside.

Available here:

2 Likes

That’s a pretty interesting way of going about it. Huh. I like it.

2 Likes

The other side benefits of making such handy factories is just too great: if a “thing” needs to have a fresh Component stuck onto it, and it’s important to you how that happens, make a factory and handle it all internal to the class.

Don’t splatter .AddComponent() calls all over the place. It’s just a Bad Idea™ all around.

Factory Pattern in lieu of AddComponent (for timing and dependency correctness):

https://gist.github.com/kurtdekker/5dbd1d30890c3905adddf4e7ba2b8580

2 Likes

Since I created this topic I fell obligated to say something more after all this years when I was waiting for some response from unity team.

So now with all certainty I want more than just adding disabled component.

What we need is

AddComponet<T>(Action<T> addedCallback);

“addedCallback” would be invoked right after the component was added to the GameObject, before OnValidate/Awake etc.

Callback argument would be - yes you guessed It - component freshly added to the GameObject.

2 Likes