How to disable player input

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By amaou310

I am trying to implement knockback to my 2d platformer game project. I would like to disable player input once player enter the enemy hitbox area2d. I control player input in func get_input_direction(). I followed state machine by Nathan Lovato btw.

Player Script:

class_name Player

extends KinematicBody2D

var speed = 200
var acceleration = 30
var friction = 15
var gravity = 1500

var air_jump = true
var jump_strength = 570
var air_jump_strength := 550
var air_friction = 1

var direction := 1
var knockback := -150
var hitstate = false
var can_move = true

var _velocity := Vector2.ZERO

onready var position2D = $Position2D
onready var _animation_player: AnimationPlayer = $Position2D/PlayerSkinIK/AnimationPlayer


func get_input_direction() -> float:
	var _horizontal_direction = (
		Input.get_action_strength("move_right")
		- Input.get_action_strength("move_left")
	)
	return _horizontal_direction


func _process(delta: float) -> void:
	if get_global_mouse_position().x > $Position2D/PlayerSkinIK.global_position.x:
		position2D.scale.x=1
		direction == -1
		
	else:
		position2D.scale.x=-1
		direction == 1


func walk_flip():
	if get_global_mouse_position().x > $Position2D/PlayerSkinIK.global_position.x:
		position2D.scale.x=1
	else:
		position2D.scale.x=-1
	
	if is_on_floor() and position2D.scale.x==1 and Input.is_action_pressed("move_right"):
		_animation_player.play("Player-Run IK")
	elif is_on_floor() and position2D.scale.x==-1 and Input.is_action_pressed("move_right"):
		_animation_player.play("Player-Run IK Backward")
	elif is_on_floor() and position2D.scale.x==-1 and Input.is_action_pressed("move_left"):
		_animation_player.play("Player-Run IK")
	elif is_on_floor() and  position2D.scale.x==1 and Input.is_action_pressed("move_left"):
		_animation_player.play("Player-Run IK Backward")


func pass_through():
	set_collision_mask_bit(4, false)
	print("mask_off")
	yield(get_tree().create_timer(0.1), "timeout")
	set_collision_mask_bit(4, true)
	print("mask_on")


func _on_HurtboxPlayer_area_entered(area: Area2D):
	if area.name == "HitboxMushroom01":
		direction == -1
		print("ouch right")
		_velocity.y += -120
		_velocity.x = direction * 280


	if area.name == "HitboxMushroom02":
		direction == 1
		print("ouch left")
		_velocity.y += -120
		_velocity.x = direction * -280
		pass

Move State:

extends PlayerState

export (NodePath) var _animation_player
onready var animation_player: AnimationPlayer = get_node(_animation_player)


func enter(_msg := {}) -> void:
	pass

func physics_update(delta: float) -> void:
	player.walk_flip()
	
	if not player.is_on_floor(): #If player is not on floor, FALL STATE
		state_machine.transition_to("Fall")
		return
	
	if not is_zero_approx(player.get_input_direction()): #If Player is moving, calculate Player's velocity.x 
		player._velocity.x = lerp(player._velocity.x, player.get_input_direction() * player.speed, player.acceleration * delta)
	
	player._velocity.y += player.gravity * delta #Gravity Calculation
	player._velocity = player.move_and_slide(player._velocity, Vector2.UP)
	
	
	if Input.is_action_just_pressed("jump"): #If input jump pressed, JUMP STATE
		if Input.is_action_pressed("ui_down"):
			state_machine.transition_to("JumpDown")
		else:
				state_machine.transition_to("Jump")
	elif is_zero_approx(player.get_input_direction()): #If Player is Not Moving, IDLE STATE
		state_machine.transition_to("Idle")
:bust_in_silhouette: Reply From: Ertain

If the inputs are handled in the get_input_direction() function, then have the function check for some boolean variable that’s set when the player enters the hitbox.

var player_in_hitbox: bool = false

func _on_HurtboxPlayer_area_entered(area: Area2D):
    player_in_hitbox = true
    if area.name == "HitboxMushroom01":
        direction == -1
        print("ouch right")
        _velocity.y += -120
        _velocity.x = direction * 280

func get_input_direction() -> float:
    # Don't forget to flip this to false when the player exits the hitbox.
    if player_in_hitbox:
          return
    var _horizontal_direction = (
        Input.get_action_strength("move_right")
        - Input.get_action_strength("move_left")
    )
    return _horizontal_direction

Other than that, you can disable the input through a method like set_process_unhandled_input(false). See the documentation on Node for details.

I don’t recommend set_process_unhandled_input(false), the below method is better in my opinion

  if player_in_hitbox:
          return

because it’s flexible. If you decide to add a feature that allows a player to break free from stun or a hitbox or a parry , then the design around set_process_unhandled_input(false) falls appart but the player_in_hitbox flag logic can support it (just decide what input is allowed during what animation). More importantly, if you want to eventually support a pause feature, where player can pause the game, you may want them able to press pause (user input) while stunned

godot_dev_ | 2022-08-16 14:32

Thank you Ertaln for kindly teaching me.
“if player_in_hitbox: return” inside “func get_input_direction()” pops out an error.
“A non-void function must return value”. Do you have any idea why?

func get_input_direction() -> float:
	if player_in_hitbox:
		return

amaou310 | 2022-08-17 02:39

Whoops, forgot about the requirement of a return value.

func get_input_direction() -> float:
    # Don't forget to flip this to false when the player exits the hitbox.
    if player_in_hitbox:
          # Return some floating point number here.
          return 0.0
    var _horizontal_direction = (
 ....

Ertain | 2022-08-17 12:58

Thank you again Ertain.
It worked for x axis movement. However, I still can jump. How do I disable jump too?

amaou310 | 2022-08-17 13:07

You could handle player input centrally in one function and do the proposed solution:

if player_in_hitbox:
      # Return some floating point number here.
      return 0.0

So that no matter the input, jump, directions, it will be ignored. I assume you have some where else in your code that doesn’t make the player_in_hitbox check and processes input for jumpin

godot_dev_ | 2022-08-17 13:45

hmmm. I wonder why. Maybe because of Input.is_action_just_pressed("Jump") inside movement state?

amaou310 | 2022-08-17 13:58

In your physics_update function, maybe the following code will solve the problem.

   if not player_in_hitbox:
     if Input.is_action_just_pressed("jump"): #If input jump pressed, JUMP STATE
       if Input.is_action_pressed("ui_down"):
           state_machine.transition_to("JumpDown")
       else:
           state_machine.transition_to("Jump")
      elif is_zero_approx(player.get_input_direction()): #If Player is Not Moving, IDLE STATE
          state_machine.transition_to("Idle")

You weren’t checking the player_in_hitbox flag for you jump input checks

godot_dev_ | 2022-08-17 15:06

It worked!! Thank you very much godot_dev! I really appreciate your help.

amaou310 | 2022-08-18 14:15