Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Unity code behavior

Discussion in 'Scripting' started by Capollastre, Apr 8, 2015.

  1. Capollastre

    Capollastre

    Joined:
    Jul 15, 2014
    Posts:
    8
    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
    Code (CSharp):
    1. void Start () {
    2.         posicionpieza (origin);
    3.         creatotemprimero ();
    4.  
    5.         target.piezastarget = cuantaspiezas;
    6.        makestart ();
    7.         StartCoroutine (Lfoundry());
    8.        
    9.  
    10.  
    11.     }
    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.

    Code (CSharp):
    1. for (int lvl = 0; lvl < totemlevel ; lvl++){
    2.  
    3.             for (int y = 0; y < lapieza2.Length; y++) {
    4.                 // las tres piezas
    5.                 string el_color = color [Random.Range (0, color.Length)];
    6.  
    7.                 switch (y) {
    8.                 case 3:
    9.                     sumandox = 1.41f;
    10.                     sumandoz = -1.41f;
    11.                     break;
    12.                 case 2:
    13.                     sumandox = -1.41f;
    14.                     sumandoz = -1.41f;
    15.                     break;
    16.                 case 1:
    17.                     sumandox = -1.41f;
    18.                     sumandoz = 1.41f;
    19.                     break;
    20.                 case 0:
    21.                     sumandox = 1.41f;
    22.                     sumandoz = 1.41f;
    23.                     break;
    24.                 default:
    25.                     sumandox = 0;
    26.                     sumandoz = 0;
    27.                     break;
    28.                 }
    29.                
    30.  
    31.                 lapieza2 [y] = Resources.Load ("Cubo" + el_color + "Model") as GameObject;
    32.                 Instantiate (lapieza2 [y], new Vector3 (origin.x + sumandox, origin.y + (lvl * 2.8f), origin.z + sumandoz), Quaternion.identity);
    33.                 GameCube gamecube = lapieza2 [y].GetComponent<GameCube> ();
    34.                 gamecube.elcolor = el_color;
    35.                 lapieza2 [y].tag = "litrick";
    36.  
    37.        
    38.  
    39.  
    40.  
    41.             }
    42.            
    43.         }
    44. foreach (GameObjectpoliceinchekator) {
    45. piezasdestruidas += 1;
    46. elsubida = police.GetComponent<GameCube>().cubelevel;
    47. elpos = police.GetComponent<GameCube>().posde4;
    48. sumapuntos += (police.GetComponent<GameCube> ().CubePoints) * (x+j);
    49.  
    50. gelocatil(elpos,elsubida);
    51. Destroy (police, 1.7f);
    52.  
    53.  }
    54.  
    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 :/

    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.
    Code (CSharp):
    1. IEnumerator Lfoundry(){
    2.         yield return StartCoroutine(Gamecheck ());
    3.         if (Lfound == 0) {
    4.             startener = 0;
    5.  
    6.         } else {
    7.             startener = 1;
    8.             cambiomatches ();
    9.  
    10.         }
    11.  
    12.     }
    13.  
    14.  
    15.     void cambiomatches(){
    16.    
    17.         GameObject[] chekator;
    18.    
    19.         chekator = GameObject.FindGameObjectsWithTag ("match");
    20.         foreach (GameObject police in chekator) {
    21.        
    22.             string el_color1 = color [Random.Range (0, color.Length)];
    23.             GameObject sustituto1 = Resources.Load ("Cubo" + el_color1 + "Model") as GameObject;
    24.             Instantiate(sustituto1, police.transform.position,police.transform.rotation);
    25.        
    26.             Destroy (police);
    27.         }
    28.  
    29.         StartCoroutine (Lfoundry());
    30.     }
    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 :/
     
  2. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    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
    Code (csharp):
    1.  
    2. A();
    3. B();
    4. C();
    5.  
    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:
    Code (csharp):
    1.  
    2. A();
    3. StartCoroutine(B());
    4. C();
    5.  
    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
    Code (csharp):
    1.  
    2. IEnumerator Cor()
    3. {
    4.     A();
    5.     yield return new StartCoroutine(B());
    6.     C();
    7. }
    8.  
    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
    Code (csharp):
    1.  
    2. IEnumerator Cor()
    3. {
    4.     A();
    5.     IEnumerator b = B();
    6.     while (b.MoveNext())
    7.         yield return b.Current;
    8.  
    9.     C();
    10. }
    11.  
     
    Capollastre likes this.
  3. Capollastre

    Capollastre

    Joined:
    Jul 15, 2014
    Posts:
    8
    really interesting . i wish i had such clear info before . Thx ;)
    In your first example

    1. A();
    2. B();
    3. 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();
     
  4. ThomasCreate

    ThomasCreate

    Joined:
    Feb 23, 2015
    Posts:
    81
    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.
     
    Last edited: Apr 8, 2015
    Capollastre likes this.
  5. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    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.
     
    Capollastre likes this.