I completed this excellent 2D platformer tutorial series by Youtuber BornCG and wanted to modify the final product once completed into a more full project.
Movement is handled in the _physics_process(delta)
function of the player script by checking Input.is_action_pressed(action)
or Input.is_action_just_pressed(action)
for various actions.
After some modifications to how jumping works, I noticed that jump input was not always captured and so repeated presses of the jump button only sometimes resulted in a jump, even when the character was on the floor. After some googling, I found this SO answer which indicated that I should really be capturing my inputs in the _input(event)
function. However, the Godot Node documentation indicates that _unhandled_input(event)
is likely preferable for gameplay input, so I changed my code to the following:
var right_pressed = false
var right_strength = 0
var left_pressed = false
var left_strength = 0
var down_pressed = false
var jump_pressed = false
func _unhandled_input(event):
right_pressed = event.is_action("ui_right")
right_strength = event.get_action_strength("ui_right")
left_pressed = event.is_action_pressed("ui_left")
down_pressed = event.is_action_pressed("ui_down")
jump_pressed = event.is_action_pressed("jump")
func _physics_process(delta):
if right_pressed:
velocity.x = SPEED*(pow(3,right_strength) - 1)*delta
$Sprite.play("move_horizontal")
$Sprite.flip_h = false
elif Input.is_action_pressed("ui_left"):
left_strength = Input.get_action_strength("ui_left")
velocity.x = -SPEED*(pow(3,left_strength) - 1)*delta
$Sprite.play("move_horizontal")
$Sprite.flip_h = true
if jump_pressed and is_on_floor():
jump_pressed = false
velocity.y = JUMPFORCE*delta
$Sprite.play("jump")
$SoundJump.play()
if is_on_floor():
$Sprite.play("idle")
else:
# Not on floor #
velocity.y = velocity.y + delta*GRAVITY
if(velocity.y >= 0):
$Sprite.play("idle")
else:
$Sprite.play("jump")
velocity = move_and_slide(velocity, Vector2.UP)
if velocity.y > 0:
velocity -= Vector2.UP * GRAVITY * (FALL_MULTIPLIER - 1) * delta
elif velocity.y < 0 and not Input.is_action_pressed("jump"):
velocity -= Vector2.UP * GRAVITY * (LOW_JUMP_MULTIPLIER - 1) * delta
velocity.x = lerp(velocity.x,0,0.2)
This did not fix the jumping issue (perhaps it made it slightly better), but it did cause big issues with recognizing movement to the right on the analog stick. With the code above, movement is only recognized if the joypad is slightly tilted to the right, and even then it is spotty. Movement to the left is still handled with Input.is_action_pressed(action)
in the _physics_process(delta)
function, and it works much better.
So I guess my question is:
Should I be capturing gameplay input with Input.is_action_pressed(action)
within _physics_process(delta)
or within _input(event)
, and whichever is the case, how can I ensure that my inputs are always captured?