I have a prefab that I instantiate with two Monobehaviours (A & B) attached to it. When I instantiate the prefab, the order of the Awake/Start/Update functions between A & B is undefined. I get different orders, e,g sometimes:
Awake-A
Start-A
Update-A
Awake-B
Start-B
Update-B
or, sometimes:
Awake-A
Awake-B
Start-A
Update-A
Start-B
Upate-B
Within one Monobehaviour, the order or Awake->Start->Update is always clear.
Unity version: 2021.1.23f1
This seems to be the same issue as in:
but this post is from 2009 with no resolution, with the only Unity staff comment being “the behaviour you are seeing […] is very strange.”
Are there any news, if this is this intended/accepted or a bug?
Something is weird in your project or you’re doing something weird. You probably should submit a bug report with a minimal reproduction project.
I built a quick test-rig to check what you’re saying and I get completely normal results:
TestA.cs
using UnityEngine;
public class TestA : MonoBehaviour
{
private int _c = 0;
private void Awake() => Debug.Log("Awake A");
private void Start() => Debug.Log("Start A");
private void Update()
{
if (_c != 0) return;
Debug.Log("Update A");
_c++;
}
}
TestB.cs
using UnityEngine;
public class TestB : MonoBehaviour
{
private int _c;
private void Awake() => Debug.Log("Awake B");
private void Start() => Debug.Log("Start B");
private void Update()
{
if (_c != 0) return;
Debug.Log("Update B");
_c++;
}
}
Test.cs
using UnityEngine;
public class Test : MonoBehaviour
{
[SerializeField] private GameObject prefab;
private void Update()
{
if (Input.GetKeyDown(KeyCode.A)) Instantiate(prefab, Vector3.zero, Quaternion.identity);
if (Input.GetKeyDown(KeyCode.S))
{
var go = new GameObject("bla")
{
transform = { position = Vector3.zero }
};
go.AddComponent<TestA>();
go.AddComponent<TestB>();
}
}
}
Prefab
Results (no matter which one I execute, the results are the same):
The function itself is registered at a System.Action to be called, whenever I click on a position where the prefab can be instantiated. I don’t understand how this could cause this issue.
Will have to create a more isolated example for a bug report, otherwise I’d have to send half a project.
I have been able to reprocude my original issue (update before start) with this simple setup that mirrors my instantiation behaviour.
This is the output I get:
edit: this order seems to be constant, i.e. it is always Awake x2, Start/Update, Start/Update
both DummyA and DummyB (has A replaced with B, no need to post the code twice)
public class DummyA : MonoBehaviour
{
private bool _singleLog = true;
private void Awake()
{
Debug.Log($"{name} - A - Awake"); # replace A with B for DummyB
}
// Start is called before the first frame update
void Start()
{
Debug.Log($"{name} - A - Start");# replace A with B for DummyB
}
// Update is called once per frame
void Update()
{
if (_singleLog)
{
Debug.Log($"{name} - A - Update");# replace A with B for DummyB
_singleLog = false;
}
}
}
the objects I click on in the game:
public class Clickable : MonoBehaviour
{
public static Action<Clickable> OnClicked;
private void OnMouseUpAsButton()
{
OnClicked?.Invoke(this);
}
}
where the GOs are instantiated:
public class Instantiater : MonoBehaviour
{
public GameObject Prefab;
// Start is called before the first frame update
void Start()
{
Clickable.OnClicked += SpawnPrefab;
}
private void SpawnPrefab(Clickable obj)
{
GameObject go = Instantiate(Prefab, obj.transform.position, Quaternion.identity);
}
}
Resolved
This behaviour is as intended, and caused by triggering it from OnMouseUpAsButton. As this is called between Start and Update (Unity - Manual: Order of execution for event functions), it will call Start on each script right before it goes into the Update phase.