Reproducibly getting disabled objects to run update() once

There's a race condition of some sort in Unity 2023.3.0b8.git.7962477.

  • Add a Player Input component and define any key as a button.
  • In the input handler, add this code:
public class ReceiveKey : MonoBehaviour
{
    void OnTrigIt(InputValue value) {
        gameObject.AddComponent<Testit>();
    }
}
  • A TestIt script with this code:
public class Testit : MonoBehaviour
{
    void Awake() {
        Debug.Log($"Awake was called at FrameCount {Time.frameCount} on {name} ({GetInstanceID()}) with enabled state: {enabled}", this);
        enabled = true;
    }

    void Start() {
        Debug.Log($"Start was called at FrameCount {Time.frameCount} on {name} ({GetInstanceID()}) with enabled state: {enabled}", this);
        enabled = false;
        Debug.Log("end of start");
    }

    void OnEnable() {
        Debug.Log($"OnEnabled was called at FrameCount {Time.frameCount} on {name} ({GetInstanceID()}) with enabled state: {enabled}", this);
    }

    void OnDisable() {
        Debug.Log($"OnDisable was called at FrameCount {Time.frameCount} on {name} ({GetInstanceID()}) with enabled state: {enabled}", this);
    }

    void Update() {
        Debug.Log($"================================ Update was called at FrameCount {Time.frameCount} on {name} ({GetInstanceID()}) with enabled state: {enabled}", this);
    }

}
  • Run it and press your registered key.

You'll see that Unity runs the Update() function once even though the GO is disabled. Pretty annoying bug.

To show that it's a race condition, this is a workaround that fixed the race condition:

public class ReceiveKey : MonoBehaviour
{
    void OnTrigIt(InputValue value)
    {
        Invoke("Foo",0.1f);
    }

    void Foo()
    {
        gameObject.AddComponent<Testit>();
    }
}