How do I prevent an input from being spammed?

Im learning to writing a script right now that swaps the position from two game objects and while the code that I wrote works, I can hold down the space button and it makes it constantly move until I let go of the button.

using System.Collections;
using System.Collections.Generic;
using System.Threading;
using UnityEngine;

public class PositionSwapper : MonoBehaviour
{
    public GameObject objectA;
    public GameObject objectB;
    // Update is called once per frame
    void Update()
    {
        SwapPositions(objectA, objectB);
    }
    private void SwapPositions(GameObject objectA, GameObject objectB)
    {
            if (Input.GetKey(KeyCode.Space))
            {
                Vector3 tempPosition = objectA.transform.position;
                objectA.transform.position = objectB.transform.position;
                objectB.transform.position = tempPosition;
             }
    }
}

You’ll need to use Input.GetKeyDown(), which fires only once per key press.

5 Likes

One trick is to use Time.time to keep track of the last time something occurred, then calculate the elapsed time which has passed.

public GameObject objectA;
    public GameObject objectB;
    // Update is called once per frame

    private float lastSwapTime;

    void Update ()
    {
        SwapPositions (objectA, objectB);
    }

    private void SwapPositions (GameObject objectA, GameObject objectB)
    {
        if (Time.time - lastSwapTime > 1.0f) { //enough time has elapsed
            if (Input.GetKey (KeyCode.Space)) {
                Vector3 tempPosition = objectA.transform.position;
                objectA.transform.position = objectB.transform.position;
                objectB.transform.position = tempPosition;

                lastSwapTime = Time.time;
            }
        }
    }

This is useful for certain situations. But for your case, Nad_B’s approach above is probably best.

3 Likes

Just need to initialize lastSwapTime to something smaller than -1, or you won’t be able to swap objects for the 1st second of the game :smile:

True, but usually with the amount of time it takes to start the game, load level, or wait for play mode to become entered, one second has already elapsed, which is why i just leave it at 0, LOL.

1 Like

Input.GetKey returns true every frame the button is held down. If you only want to register a key press once and then not register it again until the user releases and presses it again you need to use Input.GetKeyDown.

1 Like

Right, though that’s why it usually makes more sense to work with a timeout rather than a “lasttime”. So when you execute an action, you set the timeout and in the check the value just needs to be greater than 0. Those are the two general approaches. Both have advantages and disadvantages. Using a timeout also doesn’t require a subtraction each frame (though a comparison under the hood is essentially a subtraction) as you can just do

if (Time.time > timeout)

So the timeout is simply a point in the future

timeout = Time.time + delay;

In this case timeout can start at 0 and you don’t have to worry about the actual wait time, wether it’s half a second or 10 minutes.

2 Likes