godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.16k stars 97 forks source link

Add `is_key_just_pressed()` to the Input singleton #2016

Open emmanent opened 3 years ago

emmanent commented 3 years ago

Describe the project you are working on

I am working on a PC platformer game where the player's controls change to different keys on the keyboard. So while one level may have "A" as moving left, the next level might have it at "U".

Describe the problem or limitation you are having in your project

When I was creating a jump command, I wanted to use something like is_key_just_pressed to run some code when the jump key is pressed.

if (Input.is_key_just_pressed(SPACE)):
    // do something here

But le gasp the function does not exist! 😮

Describe the feature / enhancement and how it helps to overcome the problem or limitation

By including is_key_just_pressed, which would return true the instance a key is pressed, the above code can run without too many adjustments.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

We have an example to use when we implement this: is_action_just_pressed!

Actions are defined like this. When is_action_just_pressed is called (code is here), we know if a key is pressed based on the action's physics_frame matches the engine's.

To match this, we can build something similar for keys: make a Keys struct that includes physics frames, record keys in a new key_state map, and finally implement is_key_just_pressed similar to is_action_just_pressed.

If this enhancement will not be used often, can it be worked around with a few lines of script?

Yes it can. You currently have two options: check with event handling or use actions.

The event handling approach is documented here.

Another approach is to make a new action for every key you wanted to record, and then use is_action_just_pressed.

Is there a reason why this should be core and not an add-on in the asset library?

We have is_action_pressed and is_key_pressed. We have is_action_just_pressed, but no is_key_just_pressed. Let's make is_key_just_pressed a reality! 🥳

emmanent commented 3 years ago

I would also be willing to attempt implementing this change as well! 😀

aaronfranke commented 3 years ago

Watch out! The below code is in C#

I see the : and the snake_case naming convention and I very much I doubt this.

I am working on a PC platformer game where the player's controls change to different keys on the keyboard. So while one level may have "A" as moving left, the next level might have it at "U".

Just remap the keys/etc for the actions and then use is_action_just_pressed.

emmanent commented 3 years ago

I see the : and the snake_case naming convention and I very much I doubt this.

Ah woops, my bad. Thanks for catching that. Fixing!

Remapping keys to actions is a viable workaround (I even mention it). This enhancement's functionality definitely exists right now.

me2beats commented 3 years ago

Just remap the keys/etc for the actions and then use is_action_just_pressed.

I don't think this is handy and flexible solution in most cases. Also I often see newcomers who ask like: where is is_key_just_pressed(). So I'm for adding it, unless implementing it has some conflicts or performance issues.

CsloudX commented 3 years ago

I like and wish this feature, in some complex UI, i just want use the key instead config actions.

is_action_pressed()
is_action_just_pressed()
is_action_just_released()

is_key_pressed()
is_key_just_pressed()  # need add
is_key_just_released() # need add

why implement is_key_pressed() but others(is_key_just_pressed(),is_key_just_released() )

AThousandShips commented 1 year ago

Generally the recommended and proper way of doing input is using actions, using raw input shouldn't be your primary way of doing it IMO. Adding this functionality wouldn't be for free, and it wouldn't be a frequently used thing, or rather shouldn't be.

If you absolutely need to handle key input that doesn't have a specific action associated with it there are ways to do so that are easy to achieve, using the echo property.

The reason only is_key_pressed is implemented is that there's a difference between tracking if a key is pressed, and when it was pressed. Actions are tracked specifically, like their strength, and also when they were pressed or released. This is how they can be checked like this, this is not tracked for individual keys.

Adding this tracking is not free, there are a few different approaches, but it's not just something you can get for free. So as this doesn't seem to be very much requested, and not the generally appropriate way to do input anyway, why add this cost?

Edit: In fact I would say that unless you are dealing with an extreme situation where you need access to most of the keyboard for example the fact that you need this feature indicates you are approaching input wrong and should be using actions instead.

L2750558108 commented 1 year ago

But I've found that almost all major engines include this feature, such as GameMaker, Cocos, Unity and Unreal. This proves that this feature really needs to be used frequently, so I think it should be added.

dogman035 commented 1 year ago

It was mentioned in the duplicate post, but this would be a nice QoL feature for debugging. Primarily cases where you only need a temporary input that you'll likely remove later.

It just saves the hassle of adding and setting up an action that's meant to be deleted later anyways.

dogman035 commented 1 year ago

That said, I can see how it might distract from the input system and encourage newer developers to hardcode their inputs.

Calinou commented 1 year ago

It was mentioned in the duplicate post, but this would be a nice QoL feature for debugging. Primarily cases where you only need a temporary input that you'll likely remove later.

Personally, I'd say it would be better for you to create a generic debug action that you keep in your project and reuse when needed. You can create several of them and keep them bound to nearby keys, such as debug1, debug2, debug3 and debug4.

If creating new input actions is that much effort, we could add command palette options to speed up this process :slightly_smiling_face: You can also create input actions from code.

I'm not huge on the idea of making hardcoded keys more convenient to use, because it encourages the use of these methods in production. This leads to games having non-remappable keys when they could be made remappable, which is an accessibility problem.

passivestar commented 3 months ago

Having to always create input actions can be a little annoying tbh because it takes you out of the flow when prototyping, but at least you can do this:

func _input(event: InputEvent):
    if event is InputEventKey and event.keycode == KEY_1 and event.is_pressed():
        print("1 pressed")

I don't think not having is_key_just_pressed() will necessarily result in more games having remappable keys, realistically most beginners would just create those actions and never make the remap UI for them. Same with jam games and quick prototypes that will never see the light of day

As such I think is_key_just_pressed() is just a convenient thing to have. It matches the actions methods making the API more predictable. The only reason I see for not having it is if it actually makes the engine slower and/or is hard to add

Bfahome commented 3 months ago

I am definitely in favor of having this added, as well as an any_key_just_pressed feature. My specific case is I want to be able to have someone type in a code phrase, but have the code reset if they type a wrong letter. When I had started in Unity that was only a few lines of code with Input.anyKeyDown and Input.GetKeyDown(), but that option's not available in Godot. Using is_key_pressed won't work because holding the key is then continually registered as an input. The usual suggestion of adding in actions and using is_action_just_pressed would mean I'd have to create an action for every key on the keyboard.