Godot Version
4.3
Question
I am trying to figure out the best way to handle moving the character in my game, and the docs suggest me to use _unhandled_key_input() for gameplay input. However, using something like
func _unhandled_key_input(event: InputEvent) -> void:
velocity = Vector2(0, 0)
if event.is_action_pressed("move_left", true):
velocity.x -= speed
if event.is_action_pressed("move_right", true):
velocity.x += speed
if event.is_action_pressed("move_up", true):
velocity.y -= speed
if event.is_action_pressed("move_down", true):
velocity.y += speed
return
only lets the character move in a cardinal direction at a time(no movements at 45 degrees or such). I believe this is because when the second key is pressed after one direction key is pressed, _unhandled_key_input gets called again and velocity is reset to 0. Is there a way to use this function for moving in directions like north west or do I use the Input singleton in _physics_process(like in squash the creeps demo)?
You could try something along the following idea:
var velocity = Vector2(0, 0)
func _unhandled_key_input(event: InputEvent) -> void:
if event.is_action_pressed("move_left", true):
velocity.x -= speed
elif event.is_action_pressed("move_right", true):
velocity.x += speed
elif event.is_action_pressed("move_up", true):
velocity.y -= speed
elif event.is_action_pressed("move_down", true):
velocity.y += speed
elif event.is_action_released("move_left", true):
velocity.x += speed
elif event.is_action_released("move_right", true):
velocity.x -= speed
elif event.is_action_released("move_up", true):
velocity.y += speed
elif event.is_action_released("move_down", true):
velocity.y -= speed
return
and act on velocity
in _physics_process`.
Check out Input.get_vector()
1 Like
Thanks, but that would require using the Input singleton inside _unhandled_key_input()
, which would both make event
which is passed as a parameter to _unhandled_key_input()
pointless and can be buggy. If I was going to use the Input
singleton I’d have used is_action_pressed()
of Input
in _unhandled_key_input(). I want a solution using InputEvent
I could just write a massive if chain to detect all 8 directions if that’s what you mean, but I think that’s a last resort, and possibly worse than just using the Input
singleton
You can also just check if the event is a movement action before the get vector. it isnt buggy at all and you get a normalized vector. And you are already using the Input singleton via the _unhandled_input callback.
Whoa, the _unhandled_input
callbacks use the Input singleton? Didn’t know that
As for the buggy part, I was encountering a weird bug with interactions with walls at the start of my project, but not now, so I suppose that was not Input
related
Do inputs that are detected through the Input singleton’s functions also have the mechanism of getting accepted?
oh wait sorry I just re read your post and that makes total sense. However it’s just a bit buggy when I encounter walls in my project, move_and_slide then makes it zero and when I release the key it increases the velocity in the opposite direction. This also makes it tough to go forward when a wall is encountered.
Im not sure i understand exactly what you mean.
Every frame, As physical inputs happen, they are temporarily buffered by the input Singleton. The displayserver flushes the Singleton buffer. During the flush, global input state is updated, and inputevents/actions are created and dispatched one by one to the scenetree/viewport. There is a big order of operations you can see here.
That link also explains a lot about how to stop propagation. But general rule of thumb custom UI can use _input and game characters can use unhandled*input events.
Tbh im not sure why there is a special unhandled key input when the general purpose one can handle it all, seems kind of elitist