Search Unity

What are some methods for player input delay?

Discussion in 'Scripting' started by GIitch, Jan 9, 2019.

  1. GIitch

    GIitch

    Joined:
    Aug 1, 2013
    Posts:
    24
    Say for example, if I wanted to prevent the player from rapidly dashing in a direction. How might I introduce a delay before the buttons could be pressed again? This is the code I'm using for dashing, but as it stands, the player can spam the input or just hold it down to move faster. Does anyone have any suggestions?

    Code (CSharp):
    1.        
    2.         //dash function
    3.         if (Input.GetKey(KeyCode.Space) && (Input.GetKey(KeyCode.W))) //move up
    4.         {
    5.             transform.Translate(0, Time.deltaTime, 1, Space.World);
    6.         }
    7.         if (Input.GetKey(KeyCode.Space) && (Input.GetKey(KeyCode.A))) //move left
    8.         {
    9.             transform.Translate(-1, 0, Time.deltaTime);
    10.         }
    11.         if (Input.GetKey(KeyCode.Space) && (Input.GetKey(KeyCode.S))) //move down
    12.         {
    13.             transform.Translate(0, Time.deltaTime, -1, Space.World);
    14.         }
    15.         if (Input.GetKey(KeyCode.Space) && (Input.GetKey(KeyCode.D))) //move right
    16.         {
    17.             transform.Translate(1, 0, Time.deltaTime);
    18.         }
    19.  
     
  2. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,334
    You can record the current time when you dash, and then check how long it's since that happened.

    Code (csharp):
    1.  
    2. if (Time.time > lastDashTime + .5f) {
    3.     if (Input.GetKey(KeyCode.Space) && (Input.GetKey(KeyCode.W))) //move up
    4.     {
    5.         lastDashTime = Time.time;
    6.         transform.Translate(0, Time.deltaTime, 1, Space.World);
    7.     }
    8.     ...
    9. }
    That should get you started. Some other notes:
    - you probably want to turn those dashes into a Dash method, for easier storage
    - check the difference between GetKey and GetKeyDown - GetKey is "is it held down", while "GetKeyDown" is "was it pressed last frame".
     
    tatamlata and DaNueromancer like this.
  3. GIitch

    GIitch

    Joined:
    Aug 1, 2013
    Posts:
    24
    Thank you! That works wonderfully. :D

    I'll look into making a method for Dash. And your note on GeyKey and GetKeyDown makes the mechanic feel a lot more natural. I was able to designate Space as the command for dash and W, A, S, D now just act as directional input.

    Right now the Dash mechanic is still pretty jarring and hard to follow visually. The character kinda just snaps into position when Space is pressed. How might I control the time it takes to complete 'transform.Translate'?

    Code (CSharp):
    1.         //dash function
    2.         if (Time.time > lastDashTime + .01f)
    3.         {
    4.             if (Input.GetKeyDown(KeyCode.Space) && (Input.GetKey(KeyCode.W))) //dash up
    5.             {
    6.                 lastDashTime = Time.time;
    7.                 transform.Translate(0, 10, Time.deltaTime);
    8.             }
    9.             if (Input.GetKeyDown(KeyCode.Space) && (Input.GetKey(KeyCode.A))) //dash left
    10.             {
    11.                 lastDashTime = Time.time;
    12.                 transform.Translate(-10, 0, Time.deltaTime);
    13.             }
    14.             if (Input.GetKeyDown(KeyCode.Space) && (Input.GetKey(KeyCode.S))) //dash down
    15.             {
    16.                 lastDashTime = Time.time;
    17.                 transform.Translate(0, -10, Time.deltaTime);
    18.             }
    19.             if (Input.GetKeyDown(KeyCode.Space) && (Input.GetKey(KeyCode.D))) //dash right
    20.             {
    21.                 lastDashTime = Time.time;
    22.                 transform.Translate(10, 0, Time.deltaTime);
    23.             }
    And if it's not too much to ask I had another question related to this code.

    The script "transform.Translate(0, 0, Time.deltaTime);" doesn't support the Z axis for some reason. Writing it like "transform.Translate(0, 0, 0, Time.deltaTime);" gives me the error "CS1503: Argument 4: cannot convert from 'float' to 'UnityEngine.Space'" and I was wondering if you knew a solution or some kind of workaround.
     
  4. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,334
    For your first question, you'll want to move it over time. You can either set it up with a coroutine, or get a tweening library. Both DoTween and LeanTween are good, but if you're learning things, learning to create coroutines is pretty useful. There's plenty of tutorials, search for "Unity Coroutine tutorial" or something like that.

    For the second question, you're not doing what you think you are - I just missed it the first time around. This:

    transform.Translate(-10, 0, Time.deltaTime);


    Translates the object -10 on the x-axis and Time.deltaTime on the z-axis. Since it's an instant dash, you don't need to adjust for frame independence (what you usually do when multiplying with deltaTime).

    You can look at all of the versions of Time.deltaTime here. You're using the one with the signature:
    public void Translate(float x, float y, float z);



    If you want to scale by deltaTime, you can either multiply the relevant parameter:
    transform.Translate(-10 * Time.deltaTime, 0, 0);


    Or create a vector that you multiply:
    transform.Translate(new Vector3(-10, 0, 0) * Time.deltaTime);


    None of those make sense for a dash, though, you don't want the length of the dash to depend on the framerate of your game. It makes sense for movement, as you want the length of your per-frame movement to be shorter if the framerate is higher.
     
  5. GIitch

    GIitch

    Joined:
    Aug 1, 2013
    Posts:
    24
    I looked into the options you mentioned. DoTween will work nicely. I think Coroutines are a bit too advanced for me right now. I'm having a really hard time wrapping my head around it. The Unity tutorial was very dense and it made me feel like I skipped way too many steps. That being said, I'll keep that system in mind as I learn more.

    Right so, that was poor communication on my part. I probably have the axis types mixed up and I haven't given you any context for the type of game I'm building. To put it in my own words, the character can move left, right, forwards, and backwards with that script. It will not accept a third axis to move up and down on the same plane as left and right.

    Here's a rough visual for what I'm trying to do — https://i.imgur.com/1qqGL7i.png

    You also mentioned that the Dash code I'm using now might introduce problems because it's tied to framerate. What alternatives might I consider?
     
  6. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,334
    What, the Time.deltaTime stuff is to have the character move continually forwards on the z-axis? Or am I completely not understanding what you're getting at?
     
  7. dontdiedevelop

    dontdiedevelop

    Joined:
    Sep 18, 2018
    Posts:
    68
    Try this
    Code (CSharp):
    1.  
    2. float dashSpeed = 10;
    3. void Update()
    4.     {
    5.         if (Time.time > lastDashTime + .01f)
    6.         {
    7.             if (Input.GetKeyDown(KeyCode.Space) && (Input.GetKey(KeyCode.W))) //dash up
    8.             {
    9.                 lastDashTime = Time.time;
    10.                 StopAllCoroutines();
    11.                 StartCoroutine(changeMyPosition(new Vector3(0, 10, transform.position.z)));
    12.             }
    13.             else if (Input.GetKeyDown(KeyCode.Space) && (Input.GetKey(KeyCode.A))) //dash left
    14.             {
    15.                 lastDashTime = Time.time;
    16. StopAllCoroutines();
    17.                 StartCoroutine(changeMyPosition(new Vector3(-10, 0, transform.position.z)));
    18.             }
    19.             else if (Input.GetKeyDown(KeyCode.Space) && (Input.GetKey(KeyCode.S))) //dash down
    20.             {
    21.                 lastDashTime = Time.time;
    22. StopAllCoroutines();
    23.                 StartCoroutine(changeMyPosition(new Vector3(0, -10, transform.position.z)));
    24.             }
    25.             else if (Input.GetKeyDown(KeyCode.Space) && (Input.GetKey(KeyCode.D))) //dash right
    26.             {
    27.                 lastDashTime = Time.time;
    28. StopAllCoroutines();
    29.                 StartCoroutine(changeMyPosition(new Vector3(10, 0, transform.position.z)));
    30.             }
    31.         }
    32.     }
    33.  
    34.     IEnumerator changeMyPosition(Vector3 position)
    35.     {
    36.         while(transform.position != position)
    37.         {
    38.             transform.Translate(position * Time.deltaTime * dashSpeed);
    39.             yield return null;
    40.         }
    41.     }
     
    Last edited: Jan 10, 2019
  8. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,334
    @dontdiedevelop, You're mixing the position you're moving to and the translation vector, so you'll be eg. moving towards the right as long as the position isn't exactly (10, 0, 0), which is wrong.

    Also, even if the code wasn't broken, that's a really bad idea. You'll start a bunch of those coroutines if you tap the movement, and they'll all be fighting each other to move the character.
     
  9. dontdiedevelop

    dontdiedevelop

    Joined:
    Sep 18, 2018
    Posts:
    68
    Dude, i'll give the idea he can stop coroutine when starting then positions can not be mixed. You're trying to use time.delta time with translate in Input.getkeydown() :D when translate himself? every keydown? coroutine is better than your idea, because your idea is doesnt work
     
  10. GIitch

    GIitch

    Joined:
    Aug 1, 2013
    Posts:
    24
    Hm? That's not quite it. Imagine the character falling on the Y axis. I'm trying to enable moving left, right, up, and down while they fall. The X and Y axes are where that movement should take place but the code "transform.Translate(0, 10, Time.deltaTime);" only has two of those three axes available. I've tried the other methods you listed but none of them enable dashing like this one does.

    Thank you for the offer to help. I tried the code you posted but I don't think it works with the way I've got things setup right now. There aren't any errors, but the character isn't dashing. You've got the right idea though. The bit of code you had in there, "transform.position.z" is similar to what I'd need for the previous method. And it's not that his idea doesn't work, I think I just failed to communicate the necessary context.

    Regardless, I appreciate having a coroutine example. That'll definitely help me get a grasp of the concept when I need it.
     
  11. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,334
    What do you believe this line does:

    Code (csharp):
    1. transform.Translate(0, 10, Time.deltaTime);
    ?
     
  12. GIitch

    GIitch

    Joined:
    Aug 1, 2013
    Posts:
    24
    In my usage, it moves the character downwards on the Y axis. -10 moves them in the opposite direction or up in the context I've seen it implemented.
     
  13. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,334
    But why do you have the Time.deltaTime there? It seems really strange to move them 10 on the y-axis and then a little bit on the z-axis. Is it to move continually on the z-axis?


    Anyway, the main problem you're having is still a bit confusing, but it sounds like you want the character to move relative to the camera rather than the world axes? In that case, you'll want to feed your movement vector through the camera's transform's TransformDirection.