+3 votes

Sorry if this is too simple, but...
I want an event to trigger when a key is pressed and/or released, but not keep triggering while the key is pressed/released. I can do this manually with something like the following:

if(Input.is_action_pressed("player_shoot")):
        if(!just_fired):
            missile_launcher.launch(state)
        just_fired=true
    else:
        just_fired=false

But I was wondering if there's a better (built into godot) way...

in Engine by (146 points)

There are many answers for that already, some...:

And the development version has an experimental just pressed and just released, but has some issues with modifier keys.

3 Answers

+5 votes
Best answer

You can write the code into _input() function instead. Like this example.

func _input(event):
 if(event.is_action_pressed("ui_select")):
  print("Action pressed !")

This code prints the message only once.

by (516 points)
selected by

I made the test. The message is displayed only once no matter the press duration.
Maybe my code has a hidden drawback ?

You are right, it is weird, used to work that way, no idea when or what changed.

I've hidden my answer to prevent confussion, will keep testing on this to be sure.

If someone hasn't figured this out yet, I'd like to help: You need setprocessinput(true) at func _ready()

func _ready():
    set_process_input(true)

func _input(event):
    #this event is called once per key-press
    if event.is_action_pressed("ui_accept"):
        # do stuff
        print("You pressed ui_accept key!")
    #you can have different key-presses checked here
    elif event.is_action_pressed("ui_cancel"):
        # do other stuff
        print("You pressed ui_cancel key!")

@Jukepoks1 I'm just confused because actions are not reporting any echo, maybe I'm mistaken and that only happens with key press...

Thanks!
Using the event argument instead of Input. for my actions fixed a lot of my input problems.

+1 vote

Hi,

I saw your sample code and I guess you are trying to limit the shot rate of a weapon. I will show you one solution I use, others are possible.

I use a Timer node with mode One shot and allow the player to shot only if time left of timer is equal to 0. In the if (when allowed to shot) I set the wait time of timer to the shooting rate expected and re start the timer.

if (Input.is_action_pressed("shot") and get_node("BulletTimer").get_time_left() == 0):

    # some shot code....

    get_node("BulletTimer").set_wait_time(SHOOTING_RATE) # set the new wait time for the time
    get_node("BulletTimer").start() # restart the timer

Timer node :
Process mode : Idle
Wait time : 0.01
One shot : checked
Autostart : checked

Wait time to 0.01 and Autostart checked is only here for the start of the game, before the first shot ! After the first shot you manage it by code

by (368 points)
+3 votes

This is not much different than what you have, but might work/look a little better.

var shot_held = false


func _process(delta):
    var SHOOT = Input.is_action_pressed('player_shoot')

    if SHOOT and not shot_held:
        weapon.shoot() # do whatever you do when you shoot

    shot_held = SHOOT

This will give you that 'semi-automatic' input behavior. The shoot action will only trigger once per time the action is pressed, but will fire as quickly as the player can press that input.

by (1,326 points)
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read Frequently asked questions and How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to [email protected] with your username.