Search Unity

why are the elements in List function executed simultaenously?

Discussion in 'Scripting' started by chloeclays, Nov 28, 2022.

  1. chloeclays

    chloeclays

    Joined:
    Sep 28, 2022
    Posts:
    12
    I want to make a game where the user can drag and drop movement (left, right, up, down)(this is stored as method in the list) and press Play button, then the game object will move accordingly.

    But the problem is, the elements in the list are executed simultaneously?

    Here is the code.

    Code (CSharp):
    1. using System;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5. using UnityEngine.UI;
    6.  
    7.  
    8.  
    9. public class Controller : MonoBehaviour
    10. {
    11.     public delegate void FuntionsList();
    12.  
    13.     public GameObject mainTarget; //target object of the code is for
    14.     List<Function_> sequence; //list of functions (type Functions_). The code sequence is read from here
    15.     private int isPlaying;
    16.  
    17.  
    18.  
    19.     MainLoop loop1;
    20.  
    21.     public void Play()
    22.     {
    23.         sequence.Clear();
    24.      
    25.  
    26.         sequence = TranslateCodeFromBlocks(transform.parent, sequence);
    27.  
    28.         foreach (var sequence in sequence)
    29.         {
    30.             Console.WriteLine(sequence);
    31.         }
    32.  
    33.         isPlaying = 2;
    34.         loop1 = new MainLoop(mainTarget, sequence);
    35.         StartCoroutine(loop1.Play());
    36.  
    37.  
    38.  
    39.     }
    40.  
    41.     public void Stop()
    42.     {
    43.         StopCoroutine(loop1.Play());
    44.     }
    45.  
    46.     void Start()
    47.     {
    48.         isPlaying = 0;
    49.         sequence = new List<Function_>();
    50.     }
    51.  
    52.     void Update()
    53.     {
    54.           if (isPlaying == 2) //play
    55.           {
    56.  
    57.               if (loop1.end == true)
    58.               {
    59.                   StopCoroutine(loop1.Play());
    60.               }
    61.           }
    62.           if (isPlaying == 1) //stop
    63.           {
    64.               StopCoroutine(loop1.Play());
    65.  
    66.           }
    67.     }
    68.  
    69.     //recursive parser function
    70.     private List<Function_> TranslateCodeFromBlocks(Transform parent, List<Function_> sequence_)
    71.     {
    72.         foreach (Transform child in parent)
    73.         {
    74.            
    75.             var functionName = child.name.Split('_'); //looks like a little face ^^
    76.  
    77.             string function1 = functionName[0];
    78.             if (function1 == "Function") // Not executed
    79.             {
    80.                 string function = functionName[1];
    81.  
    82.              
    83.                 switch (function)
    84.                 {
    85.  
    86.                     case "MoveRight":
    87.                         sequence_.Add(new MoveRight("MoveRight"));
    88.                         break;
    89.                     case "MoveLeft":
    90.                         sequence_.Add(new MoveLeft("MoveLeft"));
    91.                         break;
    92.                     case "MoveUp":
    93.                         sequence_.Add(new MoveUp("MoveUp"));
    94.                         break;
    95.                     case "MoveDown":
    96.                         sequence_.Add(new MoveDown("MoveDown"));
    97.                         break;
    98.  
    99.                 }
    100.             }
    101.         }
    102.  
    103.         return sequence_;
    104.     }
    105.  
    106. }
    107.  
    108. public class MainLoop //This is the loop
    109. {
    110.     GameObject mainTarget;
    111.     List<Function_> sequence_; //After add all the movement from the trasnsform parent
    112.     public bool infiniteLoop;
    113.     public bool end;
    114.     private float waitTime;
    115.  
    116.     public MainLoop(GameObject mainTarget, List<Function_> sequence_)
    117.     {
    118.         this.end = false;
    119.         //this.moveSpeed = MoveSpeed;
    120.         this.mainTarget = mainTarget;
    121.         this.sequence_ = sequence_;
    122.         this.waitTime = 2f; //wait time between functions in sequence (list)
    123.  
    124.     }
    125.     public IEnumerator Play()
    126.     {
    127.         foreach (var sequence in this.sequence_)
    128.         {
    129.             Console.WriteLine(sequence);
    130.         }
    131.  
    132.         WaitForSeconds wait = new WaitForSeconds(waitTime);
    133.         this.end = true;
    134.         foreach (Function_ fun in this.sequence_)
    135.         {
    136.             fun.Func(this.mainTarget);
    137.  
    138.         }
    139.         yield return wait;
    140.         this.end = true;
    141.     }
    142.  
    143. }
    144.  
    145.  
    146. public class MoveUp : Function_
    147. {
    148.     public MoveUp(string ID) : base(ID)
    149.     {
    150.         this.ID = ID;
    151.     }
    152.  
    153.     override public void Func(GameObject mainTarget)
    154.     {
    155.  
    156.  
    157.        
    158.         mainTarget.GetComponent<Rigidbody2D>().AddForce(new Vector2(0, -10) * 5f);
    159.  
    160.      
    161.     }
    162. }
    163.  
    164. public class MoveDown : Function_
    165. {
    166.     public MoveDown(string ID) : base(ID)
    167.     {
    168.         this.ID = ID;
    169.     }
    170.  
    171.     override public void Func(GameObject mainTarget)
    172.     {
    173.  
    174.  
    175.  
    176.         mainTarget.GetComponent<Rigidbody2D>().AddForce(new Vector2(0, 10) * 5f);
    177.     }
    178. }
    179.  
    180. public class MoveRight : Function_
    181. {
    182.     public MoveRight(string ID) : base(ID)
    183.     {
    184.         this.ID = ID;
    185.     }
    186.  
    187.     override public void Func(GameObject mainTarget)
    188.     {
    189.    
    190.         mainTarget.GetComponent<Rigidbody2D>().AddForce(new Vector2(-10, 0)* 50f); //Add force when something trigger it to move drag and drop
    191.     }
    192. }
    193.  
    194. public class MoveLeft : Function_
    195. {
    196.     public MoveLeft(string ID) : base(ID)
    197.     {
    198.         this.ID = ID;
    199.     }
    200.  
    201.     override public void Func(GameObject mainTarget)
    202.     {
    203.      
    204.  
    205.         mainTarget.GetComponent<Rigidbody2D>().AddForce(new Vector2(10, 0) * 5f);
    206.     }
    207. }
    208.  
    209.  
    210.  
    211. public class Function_
    212. {
    213.     public string ID;
    214.  
    215.     //contructor for sinple functions
    216.     public Function_(string ID)
    217.     {
    218.         this.ID = ID;
    219.     }
    220.  
    221.     public virtual void Func(GameObject mainTarget)
    222.     {
    223.  
    224.     }
    225.  
    226. }
    My problem looks like this.
    https://imgur.com/ToE2bzI

    Is there anything else I should add in the game object physics or anything?

    I want the elements (which is the movement Vector) to execute one by one? Block by block. How can I do that?
     
  2. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,497
    Please restrict your use of the 2D forum to 2D specific questions.

    I'll move your post to the scripting forum.
     
  3. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    7,930
    You posted a still image so hard to say what the problem is.

    But generally code happens top to bottom, one thing at a time. So if it isn't behaving as expected, time to get to debugging.
     
  4. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    4,004
    Things we can say right away:

    • Your "tasks" actually use Unity engine methods that can only be used on the main thread.
    • That means it's not possible that you run those on seperate threads actually simultaneously
    • Normal functions always complete within the same frame. So executing a method means you transfer the control to that method and once the method has finished the control is given back to the caller. Usually the Unity engine is at the top and is calling your Update, Start or other callbacks. As long as your code runs, the engine is halted until you give control back to the engine.
    • Coroutines allow you to actually stop the execution and yield control back to the engine with the yield keyword and have it resumed later.
    • While your Play method of your MainLoop is a coroutine, you actually invoke all your normal methods inside a foreach loop. So once one of the methods has finished, you immediately invoke the next one, all within the same frame befoer Unity actually has any chance to do anything.
    It's not quite clear what a task like "MoveUp" is supposed to do. Currently you only apply a force which would cause a velocity change of the rigidbody. That means the next physics update the object would probably start moving. However as you run through all your tasks in one go, the object would not move at all until your yield statement. It's also not clear how that single add force would actually do what you want.