Unity code behavior

Hello Peeps, I would like to bring up a new topic as a new C# and unity3d user i found some fundamentals not very clear ( probably i misunderstand sth ).
This is about code execution behavior , I made a small project and I am having a bit execution order ( or better say disorder ) issues that causes many bugs.
After the first glance of the Unity Manual things came pretty simple about code execution order but lets make things clearly.

CASE A. Given this Start Function the function

void Start () {
        posicionpieza (origin);
        creatotemprimero ();

        target.piezastarget = cuantaspiezas;
       makestart ();
        StartCoroutine (Lfoundry());
       


    }

I need that function makestart its executed just After creatotemprimero its already finished. the thing is Creatotemprimero() has a lot of Resources.load and instantiate prefabs inside a for loop it ( lets say its a heavy function ).
The question is even i write it on code before its executed at the same time or it may happen that the for loop is long and the code continues loading the rest and the function makestart() is essentially needed to manage the resources loaded by the function before … ( is only coroutines the only thing to manage this??? )…

CASE B. More deep core routines.

for (int lvl = 0; lvl < totemlevel ; lvl++){

            for (int y = 0; y < lapieza2.Length; y++) {
                // las tres piezas
                string el_color = color [Random.Range (0, color.Length)];

                switch (y) {
                case 3:
                    sumandox = 1.41f;
                    sumandoz = -1.41f;
                    break;
                case 2:
                    sumandox = -1.41f;
                    sumandoz = -1.41f;
                    break;
                case 1:
                    sumandox = -1.41f;
                    sumandoz = 1.41f;
                    break;
                case 0:
                    sumandox = 1.41f;
                    sumandoz = 1.41f;
                    break;
                default:
                    sumandox = 0;
                    sumandoz = 0;
                    break;
                }
               

                lapieza2 [y] = Resources.Load ("Cubo" + el_color + "Model") as GameObject;
                Instantiate (lapieza2 [y], new Vector3 (origin.x + sumandox, origin.y + (lvl * 2.8f), origin.z + sumandoz), Quaternion.identity);
                GameCube gamecube = lapieza2 [y].GetComponent<GameCube> ();
                gamecube.elcolor = el_color;
                lapieza2 [y].tag = "litrick";

       



            }
           
        }
foreach (GameObjectpoliceinchekator) { 
piezasdestruidas += 1;
elsubida = police.GetComponent<GameCube>().cubelevel;
elpos = police.GetComponent<GameCube>().posde4;
sumapuntos += (police.GetComponent<GameCube> ().CubePoints) * (x+j);

gelocatil(elpos,elsubida);
Destroy (police, 1.7f);

 }

I have again one big For lets say totem level its 2000 or 1 million or 1 billion .so the of is very huge … then i call a foreach… Is the foreach always wait the for function ends? or could be executed at same time? this things is killing me :confused:

CASE C: Coroutines
Lets say coroutines exist for execution order something
so I am used to concatenate coroutines and yield return 0, at start so its supposed to wait next frame to load.

IEnumerator Lfoundry(){
        yield return StartCoroutine(Gamecheck ());
        if (Lfound == 0) {
            startener = 0;

        } else {
            startener = 1;
            cambiomatches ();

        }

    }


    void cambiomatches(){
   
        GameObject[] chekator;
   
        chekator = GameObject.FindGameObjectsWithTag ("match");
        foreach (GameObject police in chekator) {
       
            string el_color1 = color [Random.Range (0, color.Length)];
            GameObject sustituto1 = Resources.Load ("Cubo" + el_color1 + "Model") as GameObject;
            Instantiate(sustituto1, police.transform.position,police.transform.rotation);
       
            Destroy (police);
        }

        StartCoroutine (Lfoundry());
    }

Is this possible to cambiomathes will be excuted at same time that foundry? I have the feeling that i have to use only Enumerators to get the code well executed but a voice inside is telling me i am doing something wrong :confused:

It’s a bit hard to understand what you’e asking but - at a high level, nothing is executing in parallel. If you have code like this

A();
B();
C();

It will execute A to completion then B to completion and then C to completion - in order.

If B happens to be a coroutine and you’re doing this:

A();
StartCoroutine(B());
C();

then A will execute to completion, B will execute until it encounters some kind of yield instruction, and then C will execute to completion. In subsequent frames, B is re-visited and executed from the previous yield instruction until it encounters another yield or it completes.

A wrinkle would be something like this

IEnumerator Cor()
{
    A();
    yield return new StartCoroutine(B());
    C();
}

This (executed as a coroutine itself) would execute A to completion, then in the same frame execute B until a yield is encountered. B would be visited on subsequent frames like the previous example. Only after it completes (which could be N number of frames later) would C execute. This mechanism is essentially a way to block C until B finishes but allow B to execute across multiple frames.

You could also write the last example like this which might be clearer

IEnumerator Cor()
{
    A();
    IEnumerator b = B();
    while (b.MoveNext())
        yield return b.Current;

    C();
}
1 Like

really interesting . i wish i had such clear info before . Thx :wink:
In your first example

    • A();
  • B();
  • C();

if inside A() u call other script… it will waits for other script (start awake functions ) are loaded to jump b? or just the fact of call the script ints enough for pass to B();

Start() and Awake() functions are not called when another script calls a function in that script, they are called by the engine. When the game starts, the engine will call the Awake() functions of all scripts in order (whether or not they are enabled), then the Start() function of all active scripts. Each Awake() and Start() will be executed entirely if there are no coroutines being started. When a new MonoBehaviour is instantiated, its Awake() and Start() functions will be called by the engine on the frame that this happened.

You can change the order in which the engine calls these functions in Edit > Project Settings > Script Execution Order.

1 Like

Calling methods on a script from another script’s Awake method could result in null references. There is no guarantee that the thing being called has been initialized.

If you need to access other scripts/components then it should be done from Start. Start is called after every components’ Awake has been called; so you know it’s at least initialized.

1 Like