Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

How can I slow down the process of automoving

Discussion in 'Scripting' started by Lslightly, May 24, 2020.

  1. Lslightly

    Lslightly

    Joined:
    May 23, 2020
    Posts:
    2
    I'm not a native English. Sorry for my poor expressions.

    I'm making a HanoiTower Game now. And I want to have a Automove function(method?).
    the following is the code.

    Code (CSharp):
    1.  
    2. //  function:  
    3.     //  parameters:
    4.     //      a:      current pole
    5.     //      b:      
    6.     //      c:      goal pole
    7.     //      size:       the number of stones needed to be moved
    8. public void AutoMove(int a, int b, int c, int size)
    9.     {
    10.         if (size == 1)  //      one object
    11.         {
    12.             TempStone = Poles[a].GetTopStone(); //  select the top stone in the Pole[a]
    13.             TempStone.PickUp(); //      pick up it
    14.             while (Mathf.Abs(TempStone.targetY - TempStone.transform.position.y) > 0.1f)
    15.             {
    16.                 TempStone.UpdatePosition(); // this will update the position of the selected stone (operations above won't move the stone visibly, but this will)
    17.                 // Pause_In_a_Second();
    18.             }
    19.             TempStone.UpdatePosition(); //  update the position to make the stone located at the accurate position
    20.             // Invoke("Pause_In_a_Second", 2f);
    21.             if (c - a > 0)  //      goal position is in the right of the current position
    22.             {
    23.                 for (int i = 0; i < c - a; i++)   //     times needed to move the stone
    24.                 {
    25.                     TempStone.MoveRight();  //  move right
    26.                     while (Mathf.Abs(TempStone.targetX - TempStone.transform.position.x) > 0.1f)
    27.                     {
    28.                         TempStone.UpdatePosition();     //  update the position
    29.                         // Pause_In_a_Second();
    30.                     }
    31.                     TempStone.UpdatePosition();     // make the stone located at the accurate position
    32.                     // Pause_In_a_Second();
    33.                     // Invoke("Pause_In_a_Second", 2f);
    34.                 }
    35.             }
    36.             else    //    in the left
    37.             {
    38.                 for (int i = 0; i < a - c; i++)   //      times needed to move the stone
    39.                 {
    40.                     TempStone.MoveLeft();
    41.                     while (Mathf.Abs(TempStone.targetX - TempStone.transform.position.x) > 0.1f)
    42.                     {
    43.                         TempStone.UpdatePosition();
    44.                         Pause_In_a_Second();
    45.                     }
    46.                     TempStone.UpdatePosition();
    47.                     // Pause_In_a_Second();
    48.                     // Invoke("Pause_In_a_Second", 2f);
    49.                 }
    50.             }
    51.             Poles[a].RemoveTopStone();  //      remove the stone in the original pole
    52.             Poles[c].AddStone(TempStone);   //      add the stone in the goal pole
    53.             TempStone.Drop(Poles[c].GetPoleTopPosition());  //  now we can drop the stone
    54.             while (Mathf.Abs(TempStone.targetY - TempStone.transform.position.y) > 0.1f)
    55.             {
    56.                 TempStone.UpdatePosition(); //  make the stone move visibly
    57.                 // Pause_In_a_Second();
    58.             }
    59.             TempStone.UpdatePosition();
    60.             // Pause_In_a_Second();
    61.             // Invoke("Pause_In_a_Second", 2f);
    62.         }
    63.         else    // recursion
    64.         {
    65.             AutoMove(a, c, b, size - 1);
    66.             // Invoke("Pause_In_a_Second", 2f);
    67.  
    68.             AutoMove(a, b, c, 1);          
    69.             // Invoke("Pause_In_a_Second", 2f);
    70.  
    71.             AutoMove(b, a, c, size - 1);
    72.             // Invoke("Pause_In_a_Second", 2f);
    73.             // Pause_In_a_Second();
    74.         }
    75.     }
    76.  
    77.     public void Pause_In_a_Second()
    78.     {
    79.         while (Mathf.Abs(Time.time-last_time) < 0.1f)
    80.             ;
    81.         last_time = Time.time;
    82.     }
    my question is that when I click the button of play game in Unity, all of the stones will suddenly move from the original pole to the goal pole. I have no idea how to slow down the process to make it more clear for audience or players.

    and I think that I need help about how to slow down the while loop for TempStone.UpdatePosition(), because this will move the stone visibly

    Code (CSharp):
    1. while (Mathf.Abs(TempStone.targetX - TempStone.transform.position.x) > 0.1f)
    2.                     {
    3.                         TempStone.UpdatePosition();     //  update the position
    4.                         // Pause_In_a_Second();
    5.                     }
    I have tried Pause_In_a_Second(), which should have been a time-consuming function and if I use it, I will have enough time for the stone moving and players will see the process clearly. but the reality is that I failed to start the game, or maybe the game is always in the loop. So terribly!

    I have tried Thread.sleep(), but in vain. The game won't work.

    I have also tried Invoke("a randomly function", 1f); but it didn't work.

    It's the first time I have tried to ask help from others in English and in a English forum. Too hard for me to think up expressions. :(

    I would appreciate it if someone could help me, a poor undergraduate.

    three code files are attached.

    (the language Chinese is banned. too bad)
     

    Attached Files:

  2. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,836
    Unity's "magic functions" like Start, Update, etc. are all executed on the main Unity thread. If you pause that thread, it freezes the entire game. (Unity is waiting for your function to finish so that it can continue with the next thing.)

    If you want, you can explicitly create your own threads, and then you can do things like Thread.sleep in them. However, most of the UnityEngine namespace is not threadsafe and shouldn't be accessed from outside the main thread, so this is mostly useful for math-heavy threads that just do a bunch of calculations and then save their results somewhere for the main thread to read.

    The easiest option to do something like you describe is to use coroutines. These execute on the main thread, but they can temporarily yield control back to the Unity engine and then resume execution at a later time.

    Alternately, you can restructure your code so that instead of having one function that does the entire move, you have a function that just does one frame of the move and records how far it got, so that next frame you can call it again and do another tiny piece of movement. This is a more powerful approach because it can react to other things happening in your game while the move is in progress, but it's a bit harder to wrap your head around.
     
  3. Lslightly

    Lslightly

    Joined:
    May 23, 2020
    Posts:
    2
    thank you for your idea! it's surprising that you replied to me just 12 minutes after I released the question. Your idea lightens my road(is the expression right?:confused:)

    I will search for coroutines and might try the last option. Thank you again!