Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice
  3. Dismiss Notice

Question movetowards and waitforsecondsrealtime inconsistency

Discussion in 'Scripting' started by enthralledGameStudios, Jan 25, 2024.

  1. enthralledGameStudios

    enthralledGameStudios

    Joined:
    Jan 7, 2024
    Posts:
    3
    Hi there! I'm trying to make my player be able to move, have a delay of 5 seconds, be able to move again, delay, move, and so on and so forth. The code below lets me move, delay, and then let's me move with very inconsistent delays, some delays lasting the full 5 seconds and some lasting milliseconds.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class movementP2 : MonoBehaviour
    6. {
    7.     public float speed;
    8.     private Rigidbody rb;
    9.     private float dirx, dirz;
    10.     public bool delayTrue = true;
    11.     public float delayTime = 5f;
    12.     void Start()
    13.     {
    14.  
    15.     }
    16.  
    17.     void Update()
    18.     {
    19.         if (delayTrue)
    20.         {
    21.             if (Input.GetKeyDown(KeyCode.A))
    22.             {
    23.  
    24.                 delayTrue = false;
    25.                 transform.position = Vector3.MoveTowards(transform.position, new Vector3(-1 * speed, 5, 45), speed);
    26.             }
    27.             if (Input.GetKeyDown(KeyCode.D))
    28.             {
    29.  
    30.                 delayTrue = false;
    31.                 transform.position = Vector3.MoveTowards(transform.position, new Vector3(1 * speed, 5, 45), speed);
    32.             }
    33.         }
    34.         else
    35.         {
    36.             StartCoroutine(delayActive());
    37.             return;
    38.         }
    39.     }
    40.     IEnumerator delayActive()
    41.     {
    42.         delayTrue = false;
    43.         yield return new WaitForSecondsRealtime(delayTime);      
    44.         delayTrue = true;
    45.     }
    46.  
    47. }
    What should I change to make this code work more consistently?
     
  2. halley

    halley

    Joined:
    Aug 26, 2013
    Posts:
    2,539
    Your delayTrue=false/true in the coroutine seems to be backwards.

    If delayTrue is false in Update, you're starting a whole new coroutine, and you set it to false IN the coroutine, so it's going to start another coroutine immediately. You probably have hundreds of coroutines stacked on top of each other.

    You want the coroutine flag to be guarding against more coroutines stacking. Set delayTrue to true for the duration of the coroutine, and only start a new coroutine if the delayTrue is false.
     
  3. enthralledGameStudios

    enthralledGameStudios

    Joined:
    Jan 7, 2024
    Posts:
    3
    Great news, it's a ton more consistent you were right thank you tons!
    Bad news, it still lets me move freely without delay. I threw in a debug.log function and it looks like it delays for 5 seconds then let's me move uninhibited for 5 seconds before the coroutine can work again. Almost like a cooldown. Is there anything I can do for that?
     
  4. enthralledGameStudios

    enthralledGameStudios

    Joined:
    Jan 7, 2024
    Posts:
    3
    RESOLVED: I nested the startcoroutine at after the delayTrue = False in the if("button pressed"){} statement! We're good to go!
     
  5. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    6,896
    A coroutine seems overengineering for this, and WaitForSecondsRealtime should not be used for gameplay. If for whatever reason the game hitches for a second your timer will end a second earlier too.

    You really only need a float variable that has the expected end time:
    endTime = Time.time + 5f;

    And then check if time elapsed:
    if (Time.time > endTime)
     
  6. zulo3d

    zulo3d

    Joined:
    Feb 18, 2023
    Posts:
    1,083
    It's possible to do it in a single line:
    Code (CSharp):
    1. transform.position+=Vector3.right*(1-(int)Time.time%10/5)*Input.GetAxisRaw("Horizontal")*speed;