Hey everyone, so I’m having a really weird issue with the execution of the Start() and Update() functions in two different scripts on the same object.
Basically, I have two scripts with Start(). The expected behavior is that Start() for both scripts would be executed before Update() is on either object. And it behave like this, about 50% of the time. The other 50% however, Start() in Script A is executed, and then Update() in Script A is executed. THEN after Update() in Script A, Start() in Script B is executed.
Like I said, this happens what seems to be randomly, as I can see nothing being done to cause this on my end. No yield returns, and the issue happens in the same context, which is on loading a scene.
The way I tested this was by having a static class with a static int. In Script A Start(), Script B Start(), and Script A Update() I increase the int by one and print it out.
static class MyStaticClass
{
static int DebugInt = 0;
}
class ScriptA
{
void Start () {
MyStaticClass.DebugInt += 1;
print(MyStaticClass.DebugInt);
}
void Update () {
MyStaticClass.DebugInt += 1;
print(MyStaticClass.DebugInt);
}
}
class ScriptB
{
void Start () {
MyStaticClass.DebugInt += 1;
print(MyStaticClass.DebugInt);
}
}
Output:
1 // ScriptA Start()
2 // ScriptA Update()
3 // ScriptB Start()
So I’m not sure at this point if I’m just being stupid or what, but this is not something I want to spend all my time figuring out on my own. I’m not even like a beginner with C# in unity, which is what’s making this all the more confusing for me. Anyways, any advice is appreciated, and thanks in advance for the help.
Alright, so the issue is that I am instantiating a prefab instead of it being an object already placed in and serialized in the scene. Even if I am instantiating both objects at the same time, the Update function will be called immediately after the Start function in that MonoBehaviour, before moving onto the next MonoBehaviour to call its Start function.
This would not be the case however if the objects are already serialized in the scene before when the scene loads. For functions like Awake() and OnEnable(), those will always be called one step at a time, as would be expected.
So to clarify:
With the exception of a few unique cases, Unity does a step of the execution cycle for all applicable MonoBehaviours before it moves onto the next step for any other MonoBehaviour.
I won’t bother linking to the manual for execution order since it’s already been done a couple of times here. The language can be a little confusing (it confused me) but it does say that for Start’s definition that it operates differently based off of whether or not it is instantiated or pre-placed.
Anyways, thanks for all the help and input guys, it’s always good to hear different thoughts on an issue.
re: 4th paragraph: in an Instantiate, Awake is called right away (before the next line of code,) but Start isn't. That may be part of the confusion. The situation is more like Unity doesn't have special "run Start for newly instantiated objects" steps. After the Instantiating function finishes, Unity finds new object1, prepares to run Update, and notices Start needs to be run. Then the same for new object#2. I've never tested whether Start is even called ASAP. It may be called after a bunch of other Updates are run.
The Start function is called before Update for the same MonoBehaviour. That does not imply that all the Start functions is called before all the Update functions for all MonoBehaviour.
Start is called on the frame when a script is enabled just before any of the Update methods is called the first time.
Though this sentence is not very explicit.
If you want script A to run before script B, you have to specify their execution order, see:
All the "Start()" function execute before any of the Update() methods on any scripts. It means no Update() method will be called unless all of the "Start()" methods on all scripts have been called.
I don't see that specified in the links you sent me. It is my understanding that Script Execution Order is useful for making one monobehaviour's Start happen before another monobehaviour's. The idea that Start in one script is not called before Update in another during the same frame just doesn't make sense. That's like saying that Update could be called before Awake or OnEnable during that frame. I'm positive that when it is time for Start() to be called, it goes through each monobehaviour and calls start before it moves onto the next step for any monobehaviour.
I actually just noticed that right before you commented. I think it specifies though that that only applies for objects already in the scene, not instantiated prefabs. I do instantiate the object, but I'm unsure whether or not that means that it now doesn't do that for at the very least all of the monobehaviours on that one object.
There is a huge misunderstanding here. It never says Updates of different MonoBehaviors, it says 'Updates'. As in Updates of that script. Not updates of that GameObject. "when a script is enabled just before any of the Update methods is called" It never says anything about other scripts on the GameObject, or other GameObjects in the scene. The implication here is Update methods of THAT script. We know HOW it works. Lack of clarity in the documentation doesn't imply a bug.
You are not debugging it the right way. To make sure the order of the execution. Just print logs like this:
class ScriptA
{
void Start () {
print("Script A Start");
}
void Update () {
print("Script A Update");
}
}
class ScriptB
{
void Start () {
print("Script B Start");
}
}
Always use the “KISS” principle to make your life easy:
I know, I just wanted to make sure that it wasn't appearing in the console differently since it was throwing null reference errors at me as a result of the incorrect call order.
All Start methods normally are called before any Update method. However, Start is not called if an object is disabled. If you are enabling an object in the Start of another script, that could cause this behavior (I think).
Well, where does "brick_VERY_damaged_blue" come from then? Is it just the name of the object? Add a public variable at the beginning of the class: public Sprite brick_VERY_damaged_blue; In the inspector window, drag a Sprite object into that slot.
This is already an old post, but reading this and experiencing the same, I conclude that Start()/Update() behaviour in Unity is different for prefabs (or gameobject trees enabled later in the scene), than gameobjects that already exist and are enabled in the scene. Given that a) its behaviour is not deterministic and b) that it is completely not as expected, I think this can very well be considered a Unity bug. And also a nasty one, because this means that the app behaviour can be different when you start converting parts of you hierarchy into prefabs, say when you are tidying up things.
However, the desired effect is achievable through LateUpdate(). This will only be called once all Update()'s are called and thus all Start()'s are called
re: 4th paragraph: in an Instantiate, Awake is called right away (before the next line of code,) but Start isn't. That may be part of the confusion. The situation is more like Unity doesn't have special "run Start for newly instantiated objects" steps. After the Instantiating function finishes, Unity finds new object1, prepares to run Update, and notices Start needs to be run. Then the same for new object#2. I've never tested whether Start is even called ASAP. It may be called after a bunch of other Updates are run.
– Owen-ReynoldsThankyou so much! his has been troubling me for days. Sorry for being obscure in the first place :')
– Tinykahoona