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. Dismiss Notice

need help with wait coroutine and while loop for stepped movement

Discussion in 'Getting Started' started by moneil, Mar 6, 2020.

  1. moneil

    moneil

    Joined:
    Aug 9, 2019
    Posts:
    3
    Hi! I'd like some help with this player controller script. I've tried several different methods but had no luck. I want to get Input via Input.GetAxis, smoothly slide to destination exactly 1 unit away(or very close), then wait for some time for input debouncing before accepting next input. This code makes the cube slide too quickly, no matter how small an increment I pass in "transform.position += dir / 1000;" and not wait for the next input using the Waiter coroutine. Thanks!

    Code (CSharp):
    1. using System.Collections;
    2. using UnityEngine;
    3.  
    4. public class cubeControl : MonoBehaviour
    5. {
    6.     float h = 0f;
    7.     Vector3 startPos;
    8.     Vector3 dir;
    9.     Vector3 destination;
    10.  
    11.     void Update()
    12.     {
    13.         h = Input.GetAxis("Horizontal");
    14.  
    15.         if (h > 0)
    16.         {
    17.             Move(Vector3.right);
    18.         }
    19.         else if (h < 0)
    20.         {
    21.             Move(Vector3.left);
    22.         }
    23.     }
    24.  
    25.     private void Move(Vector3 dir)
    26.     {
    27.         startPos = transform.position;
    28.         destination = startPos + dir;
    29.         while (Vector3.Distance(transform.position, destination) > 0.1f)
    30.         {
    31.             transform.position += dir / 1000;
    32.         }
    33.         transform.position = destination;
    34.         StartCoroutine(Waiter(1f));
    35.     }
    36.     IEnumerator Waiter(float sec)
    37.     {
    38.         yield return new WaitForSeconds(sec);
    39.     }
    40. }
     
  2. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    20,134
    Coroutine delays only affect the coroutine and any code within it. Therefore to have a delay in the code we need to move the code into the coroutine. I believe the following code should work but I haven't tested it at all.

    Code (csharp):
    1. void Start()
    2. {
    3.     StartCoroutine(Move());
    4. }
    5.  
    6. void Update()
    7. {
    8.     h = Input.GetAxis("Horizontal");
    9. }
    10.  
    11. IEnumerator Move()
    12. {
    13.     while (true)
    14.     {
    15.         Vector3 dir;
    16.         if (h > 0)
    17.             dir = Vector3.right;
    18.         else if (h < 0)
    19.             dir = Vector3.left;
    20.  
    21.         startPos = transform.position;
    22.         destination = startPos + dir;
    23.         while (Vector3.Distance(transform.position, destination) > 0.1f)
    24.         {
    25.             transform.position += dir / 1000;
    26.         }
    27.         transform.position = destination;
    28.  
    29.         yield return new WaitForSeconds(1.0f);
    30.     }
    31. }
     
    Last edited: Mar 6, 2020
  3. unity_Vleje9qXfVZGhg

    unity_Vleje9qXfVZGhg

    Joined:
    Mar 7, 2020
    Posts:
    2
    Thank you! I resolved some of the errors reported in this code, but still it's not quite working. Can the "yield return" in line 29 break out of the while(true) loop? I thought this loop would just run forever. As-is, the cube just keeps going one direction in 1unit steps forever, without sliding, just teleporting to the new position. Still working on this:
    Code (CSharp):
    1. using UnityEngine;
    2. using System;
    3. using System.Collections;
    4.  
    5. public class PlayerController : MonoBehaviour
    6. {
    7.     float h = 0f;
    8.     Vector3 startPos;
    9.     public Vector3 dir;
    10.     Vector3 destination;
    11.  
    12.     void Start()
    13.     {
    14.         StartCoroutine(Move());
    15.     }
    16.  
    17.     void Update()
    18.     {
    19.         h = Input.GetAxis("Horizontal");
    20.     }
    21.  
    22.     IEnumerator Move()
    23.     {
    24.         while (true)
    25.         {
    26.             if (h > 0)
    27.             {
    28.                 dir = Vector3.right;
    29.             }
    30.             else if (h < 0)
    31.             {
    32.                 dir = Vector3.left;
    33.             }
    34.  
    35.             startPos = transform.position;
    36.             destination = startPos + dir;
    37.             while (Vector3.Distance(transform.position, destination) > 0.1f)
    38.             {
    39.                 transform.position += dir / 1000;
    40.             }
    41.             transform.position = destination;
    42.  
    43.             yield return new WaitForSeconds(1.0f);
    44.         }
    45.     }
    46. }
     
  4. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    20,134
    No. The loop will continue forever. It just won't interrupt the main thread because it will be pausing after every run thanks to the delay in the coroutine.
     
    Bill_Martini likes this.
  5. unity_Vleje9qXfVZGhg

    unity_Vleje9qXfVZGhg

    Joined:
    Mar 7, 2020
    Posts:
    2
    Thanks again @Ryiah ! I have been unable to get this to work with a coroutine despite working at it for several hours and trying every method I could find.
    Without the coroutine, it works just as I expect. Here's my working code just using update for movement. If anyone can help putting this into a coroutine or better method I'd appreciate the help.

    Code (CSharp):
    1. using UnityEngine;
    2. using System;
    3. using System.Collections;
    4.  
    5. public class PlayerController : MonoBehaviour
    6. {
    7.     public Vector3 dir;
    8.     public Vector3 target;
    9.     public bool moving = false;
    10.  
    11.     void Update()
    12.     {
    13.         float h = Input.GetAxis("Horizontal");
    14.         float v = Input.GetAxis("Vertical");
    15.  
    16.         if (h > 0 && !moving)
    17.         {
    18.             dir = Vector3.right;
    19.             target = transform.position + dir;
    20.             moving = true;
    21.         }
    22.         else if (h < 0 && !moving)
    23.         {
    24.             dir = Vector3.left;
    25.             target = transform.position + dir;
    26.             moving = true;
    27.         }
    28.         if (v > 0 && !moving)
    29.         {
    30.             dir = Vector3.forward;
    31.             target = transform.position + dir;
    32.             moving = true;
    33.         }
    34.         else if (v < 0 && !moving)
    35.         {
    36.             dir = Vector3.back;
    37.             target = transform.position + dir;
    38.             moving = true;
    39.         }
    40.         print(target);
    41.         transform.position = Vector3.MoveTowards(transform.position, target, 5f * Time.deltaTime);
    42.  
    43.         if (Vector3.Distance(transform.position, target) < 0.1f)
    44.         {
    45.             transform.position = target;
    46.             moving = false;
    47.         }
    48.     }
    49. }
     
  6. Bill_Martini

    Bill_Martini

    Joined:
    Apr 19, 2016
    Posts:
    445