Search Unity

Countdown timer before transform.Translate()

Discussion in 'Scripting' started by Like-A-Sir, Oct 7, 2015.

  1. Like-A-Sir

    Like-A-Sir

    Joined:
    Sep 14, 2015
    Posts:
    33
    Good day,

    I'm working on a teleporting script,and I want to add a waiting time before the teleportation of the player.I'm using Raycast in 2D,but I failed with a variable countdown(float of value 2),because nothing happened.I used countdown -= Time.deltaTime.Here is the script.Please tell me what is wrong?

    I forgot to mention that the game is working properly,but the transform.Trasnlate doesn't activate.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class Raycast_Teleport : MonoBehaviour {
    5.  
    6.     public LayerMask TerrainMask;
    7.     public int FacingDirection; // -1 = left , 1 = right
    8.     public float MaxTeleportDistance; // max distance the player can teleport
    9.     public float countdown = 2.0f;
    10.  
    11.     void Start () {
    12.    
    13.     }
    14.  
    15.     void Update () {
    16.  
    17.         LastKey ();
    18.         Teleport ();
    19.     }
    20.  
    21.     void LastKey()
    22.     {
    23.         if (Input.GetKeyDown (KeyCode.LeftArrow))
    24.              {
    25.             FacingDirection = -1;
    26.              }
    27.         else
    28.             if (Input.GetKeyDown (KeyCode.RightArrow))
    29.                {
    30.                      FacingDirection = 1;
    31.                }
    32.     }
    33.    
    34.  
    35.     void Teleport()
    36.     {
    37.         RaycastHit2D rayHit = Physics2D.Raycast (transform.position, new Vector2 (FacingDirection, 0), MaxTeleportDistance, TerrainMask);
    38.  
    39.         if (Input.GetKeyDown (KeyCode.X)) {
    40.  
    41.             countdown = 2.0f;
    42.             if (rayHit)
    43.             {
    44.                 // RayCastHit2D.distance will give you the length of the ray minus any collision depth
    45.                 countdown -= Time.deltaTime;
    46.                 if(countdown <= 0.0f)
    47.                 {
    48.                       transform.Translate (new Vector3 (FacingDirection * (rayHit.distance - 0.7f), 0, 0));
    49.                       countdown = 2.0f;
    50.                 }
    51.                 //Debug.Log(rayHit.distance);
    52.        
    53.             } else
    54.             {
    55.                 countdown -= Time.deltaTime;
    56.                 if(countdown <= 0.0f)
    57.                 {
    58.                     transform.Translate (new Vector3 (FacingDirection * MaxTeleportDistance, 0, 0));
    59.                     countdown = 2.0f;
    60.             }
    61.         }
    62.     }
    63.  
    64.  
    65.     }
    66. }
    67.  
    Thank you,
     
  2. Thomas-Mountainborn

    Thomas-Mountainborn

    Joined:
    Jun 11, 2015
    Posts:
    501
    If you read your code, you will see that it is not possible for the teleport to ever execute. Let's take a closer look:

    - You call Teleport() in the single frame the X key is pressed (well, technically you call it every frame and do that raycast every frame without using it 99% of the time).
    - In that single frame, you reset the global variable "countdown" to 2 seconds, then subtract Time.deltaTime from it once. "countdown" will not be zero, so none of the remaining code executes.

    The easiest and cleanest way of writing this code properly is using coroutines. Start a coroutine when you press X, use WaitForSeconds, and after that, check if you are in range of the teleporter and teleport to the desired location.
     
  3. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,775
    Nothing within that function is being executed except for on the one frame when the player presses X. If you walk through it: in a frame where the player has pressed X, countdown is set to 2, then Time.deltaTime is subtracted, and then... nothing, because Time.deltaTime is never gonna be more than 2. Then none of that executes until the next frame in which the user presses X, and even then countdown is set to 2 before anything happens.

    What you need to do is to set in motion a sequence that will happen over time. This is what Coroutines were made for!

    Code (csharp):
    1. void Update() {
    2. if (Input.GetKeyDown(KeyCode.X) ) {
    3. AttemptTeleport();
    4. }
    5. }
    6.  
    7. void AttemptTeleport() {
    8.         RaycastHit2D rayHit = Physics2D.Raycast (transform.position, new Vector2 (FacingDirection, 0), MaxTeleportDistance, TerrainMask);
    9. StartCoroutine(TeleportSequence(rayHit.point));
    10. }
    11.  
    12. IEnumerator TeleportSequence(RaycastHit2D rayHit) {
    13. float countdown = 2f;
    14. while (countdown > 0f) {
    15. countdown -= Time.deltaTime;
    16. yield return null;
    17. }
    18. if (rayHit) {
    19. transform.Translate (new Vector3 (FacingDirection * (rayHit.distance - 0.7f), 0, 0));
    20. }
    21. else {
    22. transform.Translate (new Vector3 (FacingDirection * MaxTeleportDistance, 0, 0));
    23. }
    24. }
     
    Like-A-Sir likes this.
  4. Like-A-Sir

    Like-A-Sir

    Joined:
    Sep 14, 2015
    Posts:
    33
    T
    Thank you very much Sir.It worked