Start and LateUpdate gets called but not Update

public class Foo : MonoBehaviour
{
public bool needCreateBar = false;

    void Update()
    {
        if (needCreateBar)
        {
            var gameObject = new GameObject("Bar");
            Debug.LogFormat("Creating {0}", Time.time);
            gameObject.AddComponent<Bar>();
            Debug.LogFormat("Created {0}", Time.time);
            needCreateBar = false;
        }
    }
}

public class Bar : MonoBehaviour
{
    private bool firstUpdate = true;
    private bool firstLateUpdate = true;

    private void Awake()
    {
        Debug.LogFormat("Bar Awake {0}", Time.time);
    }

    void Start()
    {
        Debug.LogFormat("Bar Start {0}", Time.time);
    }

    void Update()
    {
        if (firstUpdate)
        {
            Debug.LogFormat("Bar Update {0}", Time.time);
            firstUpdate = false;
        }
    }

    private void LateUpdate()
    {
        if (firstLateUpdate)
        {
            Debug.LogFormat("Bar LateUpdate {0}", Time.time);
            firstLateUpdate = false;
        }
    }
}

The output is:

Creating 6.733649
Bar Awake 6.733649
Created 6.733649
Bar Start 6.733649
Bar LateUpdate 6.733649
Bar Update 6.747721

The Update function was called one frame later then Start and LateUpdate. Because the gameobject was rendered once without Update, it often causes flickering.

I can overcome this by calling Update in Start, but it looks a little weired and I have to comment the code to avoid confusing others.

I’m using 2020.3.24f1

This is a really fascinating problem, I had no idea Update was skipped if you instantiate an object from Update in another script and I don’t have a good solution. Just noting down some experimentations and thoughts that could perhaps help in the search for a good solution.

My first thought was that it had to do with creating a new GameObject and then adding a component, but using Instantiate() and a prefab with a bar script on it did not result in any difference.

Next idea was that perhaps if we delayed the instantiation to the end of the frame and it would run everything correctly when instantiated the next frame. This may not be the most elegant solution but it makes the object run start → update → lateupdate the next frame and perhaps can be of some help.

public class Foo : MonoBehaviour
{
     public bool needCreateBar = false;
 
     void Update()
     {
         if (needCreateBar)
         {
            StartCoroutine("SpawnStuff");    
         }
     }

    IEnumerator SpawnStuff()
    {
             yield return new WaitForEndOfFrame(); 
             var gameObject = new GameObject("Bar");
             Debug.LogFormat("Creating {0}", Time.time);
             gameObject.AddComponent<Bar>();
             Debug.LogFormat("Created {0}", Time.time);
             needCreateBar = false;
 }
}