Start() and Update() execution issue
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.
Answer by Holy_Crapf · Jun 07, 2016 at 08:43 PM
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.
Yeah I know that Awake is called immediately after an object is instantiated. I think you're right about what Unity does with Start and Update for newly instantiated objects, which is why the order is enforced if the object is already in the scene.
From the testing I did, Start in the one script was always being called before anything that wasn't Awake.
Now it makes sense why it finished up that script's cycle before handling the other script.
Answer by ericbegue · Jun 07, 2016 at 06:06 PM
See: http://docs.unity3d.com/ScriptReference/MonoBehaviour.Start.html and: http://docs.unity3d.com/Manual/ExecutionOrder.html
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: https://docs.unity3d.com/Manual/class-ScriptExecution.html
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.
Start is called in the first frame that Update is called. Like already mentioned above. And in the doc's.
Yes I know, and I stated that as well. It is called however in the same frame. All of the event functions (with the unique exceptions of FixedUpdate() and such) are called in the same frame. Start however is called for all $$anonymous$$onoBehaviours before Update is called for any of the $$anonymous$$onoBehaviours in that frame. It can't move onto the Update step in the cycle without completing the Start step for all $$anonymous$$onoBehaviours that frame.
Start happens right before the first time Unity attempts to call that $$anonymous$$onoBehaviors Update.
Listen, you're just repeating what I am already stating. I know this, I have said this many times already. I don't how to explain it any more clearly.
Sorry about that, I've updated the main answer.
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 $$anonymous$$onoBehaviors, 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.
Not saying there is a bug, not sure where you got that from. Also it doesn't even say "Updates". It says, and I quote:
For objects added to the scene, the Start function will be called on all scripts before Update, etc are called for any of them. Naturally, this cannot be enforced when an object is instantiated during gameplay.
It says Start will be called for all scripts before any Update is called for any of those scripts. I understand it's sort of confusing language, but that's what it means. You clearly don't know how it works.
Answer by ninja_gear · Jun 07, 2016 at 06:18 PM
Using Awake() instead of Start() will fix this problem as well.
Yes I know, but for my specific code it needs to work in Start() properly. Thank you though.
Answer by UsmanAbbasi · Jun 07, 2016 at 06:23 PM
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: https://en.wikipedia.org/wiki/KISS_principle
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.
Post the original code which is throwing null error.
I would but it wouldn't help. I've tested it without the code that throws the null reference, same thing still happens. Root of the problem is that Start is happening before Update.
Answer by Flaring-Afro · Jun 07, 2016 at 08:01 PM
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).
How do you instantiate your objects? Show us some code.
Wait -- an actual Instantiate command? But you write in your Q that both scripts are on the same object, so what are you instantiating to make only script B? I'm wondering if overly complicated code is the problem.
Even so, Start for a instantiated object is called right away.
Yes, it is called right away. It's just a matter of when it happens in the first frame. I instantiated the object that Script A and B are attached to.
Your answer
Follow this Question
Related Questions
Update() and FixedUpdate() not running on C# scripts 0 Answers
FixedUpdate and Update not working in script 0 Answers
Vector3.Lerp in update, how stop? 1 Answer
When writing a txt file, it says sharing violation 1 Answer
Cant make Door Open 1 Answer