I seem to be having some issues understanding input. <br /><br />I want to make it so that one of my keys toggles debug information. I have a Panel set up with two labels as child nodes and a script to show or hide the panel. <br /><br />I thought I could use something like this to toggle the visibility:<br />

if Input.is_action_pressed("toggle_debug"):<br /> visible = !visible

<br /><br />This does work, but if you hold down the key, it will keep toggling back and forth, which is to be expected. I was hoping there would be an is_action_released() function, but alas, this does not appear to be!<br /><br />In fact, the documentation hints at there being one, but I can't seem to access it!<br /><br />It's under InputEventAction, but anytime I try to access it, it won't let me. The text stays as normal text and doesn't show as any kind of class. <br /><br />I've tried to access it as follows:<br />

if InputEventAction.is_action_released("toggle_debug"):

<br />But it keeps saying that InputEventAction identifier is not found. <br /><br />So, what do I do? Any pointers please?  G: <br />

I think the best way is to use input(event)[code]func ready():    set_process_input(true)func _input(event):    if event.is_action_released("toggle_debug"):        visible = !visible[/code]

Ah yes, that does work wonderfully! I didn't realize there was an [b]input(event):[/b] function!Here is my revised script:[code]extends Panelvar gravityTextvar walkingTextvar visible = truefunc ready():  set_process(true)  set_process_input(true)func process(delta):  # display the panel if visible is true, hide if it isn't  if visible == true:      self.show()  else:      self.hide()  # get the values for the labels  gravityText = str(round(get_parent().get_node("KinematicBody2D").velocity.y))  walkingText = str(round(get_parent().get_node("KinematicBody2D").velocity.x))    # set the text in the labels  get_node("Gravity").set_text("Gravity: " + gravityText)  get_node("Walking").set_text("Walking: " + walkingText)  # process all input eventsfunc input(event):  if event.is_action_released("toggle_debug"):      # flip the visible bool      visible = !visible[/code]Do you happen to know why the documentation doesn't discuss this more clearly? I think it needs a little more work!  ;) Also, is there a way to access [b]is_action_released()[/b] without having to use the [b]_input(event):[/b] function?

To get use the methods you find in InputEvent and its subclasses you need an object of one of those classes, so you could do something like:[code]# create eventvar ev = InputEvent()# set type indexev.type=InputEvent.MOUSE_BUTTON# button_index is only available for the above typeev.button_index=BUTTON_LEFT[/code]As shown in the [url=http://docs.godotengine.org/en/latest/tutorials/engine/inputevent.html]documentation[/url]But I don't think that is of any help in your case. [quote]Do you happen to know why the documentation doesn't discuss this more clearly?[/quote]That seems to be a general problem with the documentation.

I tried something like the following, but it doesn't register at all. [code]var event = InputEvent()event.type = InputEvent.ACTIONevent.set_as_action("toggle_debug", true) if event.is_action_released("toggle_debug"): visible = !visible print ("test")[/code]I put in under [b]process(delta):[/b]The reason I am wanting to do this is because I want to be able to use is_action_released() for things like the jump key. Granted, I could use a flag variable, but I want to be able to not have to do that.Using [b]input(event):[/b] seems to be pretty slow, at least in my experiments. It doesn't seem to update every frame, which is why I asked about accessing other functions inside of [b]InputEvent.[/b] Why doesn't my above code work? Am I misunderstanding something about the Input system?

There are at least 2 problems with this code:1. You create an event every time process(delta) is called, even if there is no input2. You set the event as pressed, so the following if statement will always result in falseSo your code example does exacyly the same as [code]func process(delta):  if false:    visible = !visible    print ("test")[/code]To get the desired result you first need to check if a specific input happend (e.g. Input.is_key_pressed()) and a flag to know if the key was just pressed, is hold down or was just released, than you got the needed information to create the event you need.I think we both agree that this approach is stupid.Conclusion:If you can't/don't want to use input(event) you should use fixed_process(delta) (which, in contrast to process(delta), is called every frame) and deal with the limitations of Input.*For a platformer I did to get used to godot I used the following script to handle the states of a key input[code]### class for input handling. Returns 4 button statesconst RELEASED = 0const JUST_PRESSED = 1const PRESSED = 2const JUST_RELEASED = 3var input_namevar prev_statevar current_statevar inputvar output_statevar state_old### Get the input name and store itfunc init(var input_name):        self.input_name = input_name        ### check the input and compare it with previous statesfunc check():        input = Input.is_action_pressed(self.input_name)        prev_state = current_state        current_state = input                state_old = output_state                if not prev_state and not current_state:                output_state = 0 ### Released        if not prev_state and current_state:                output_state = 1 ### Just Pressed        if prev_state and current_state:                output_state = 2 ### Pressed        if prev_state and not current_state:                output_state = 3 ### Just Released                return output_state[/code]It's used like this:[code]var input_states = preload("res://scripts/input_states.gd")var action_toggle_debug = input_states.new("toggle_debug")func _fixed_process(delta):  if action_toggle_debug.check() == input_states.JUST_RELEASED:    visible = !visible[/code] Hope that helpsEdit: fixed a error in the example

Ah, I see that now. I figured it probably had something to do with misunderstanding the [b]set_as_action()[/b] command.I like your script for working around the limitations of the input system, thanks for sharing! In the meantime, for my character to jump I just created a flag variable that resets once they hit the ground again. I suppose I could also do this:[code]if !Input.is_action_pressed("jump"):    keyPressed = falseelse:    keyPressed = true[/code]

You're making this way too complicated. What danjo had in his first post is all you should need. Use [tt]input(event)[/tt] with [tt]if event.is_action_pressed()[/tt] and [tt]if event.is_action_released()[/tt]. [tt]input()[/tt] fires whenever there is an input event. If you're having some kind of delay that must be a problem with the rest of your code. I have a couple platformer prototypes and they work fine, there's no lag or missed input. Setting the input event to a variable every frame is the same thing only way more complicated and inefficient. That's just asking for trouble. You're going to need a few bools for if your character is moving left or right or on the ground probably, trying to get around that with 20 lines of other code is kind of ridiculous.

This is all of my code, and there is quite significant lag when using the [b]input(event): [/b]function[b].[/b][code]extends KinematicBody2Dexport var gravity = 699.8export var walkSpeed = 275.0export var maxWalkSpeed = 275.0export var jumpHeight = 500var velocity = Vector2()var canJump = falsefunc ready(): # set fixed process to true set_fixed_process(true) set_process_input(true)func fixed_process(delta): # get the space states var pos = self.get_pos() var space_state = get_world_2d().get_direct_space_state() var result = space_state.intersect_ray(pos, Vector2(pos.x, pos.y + 20), [ self ]) # apply gravity if there is nothing beneath the player if result.empty(): velocity.y += gravity else: velocity.y = 0 # clamp velocities if velocity.x <= -maxWalkSpeed: velocity.x = -maxWalkSpeed elif velocity.x >= maxWalkSpeed: velocity.x = maxWalkSpeed if velocity.y >= gravity: velocity.y = gravity # determine death if pos.y >= 900: pos.y = 64 pos.x = 64 self.set_pos(pos) # now determine the motion! var motion = velocity * delta move(motion) # determine collision if(is_colliding()): var n = get_collision_normal() motion = n.slide(motion) velocity = n.slide(velocity) move(motion) func input(event): # determine what the action is if event.is_action_pressed("ui_left"): velocity.x -= walkSpeed elif event.is_action_pressed("ui_right"): velocity.x += walkSpeed else: velocity.x = 0 if event.is_action_released("ui_up"): velocity.y -= gravity[/code]In fact, not only does it lag, but it will entirely stop moving the player occasionally, when it's only a few pixels away from the edges of my tiles (or in some cases, about 32 pixels away, so about halfway through my tiles).Could it be a bug, or is it something to do with my ray cast perhaps?Although, I have noticed the same lag when toggling my debug text. It can take a half-second or longer for Godot to realize I have let go of the toggle key before it updates to determine whether or not it should display the info.

Do you get the same experience with the 2d/kinematic_char demo?

No, but that's because it doesn't use [b]_input(event):[/b], at least as far as I can tell. It's using vars to store things like Input.is_action_pressed("jump").Well, I guess for now my solution is to just use flag variables. Thankfully, I only need this for two things - jumping, and toggling debug information. Otherwise, I may just have to steal that script you previously shared!

My fault, I should have had a closer look at the demo first..I built a simple scene with your script attached to a KinematicBody2D, I didn't notice any lag.What I noticed is, that the player only moves a certain amount of time and then stops when I hold the key down, as soon as I release the key and press again it starts moving again. Not sure why this happens.. I always used RigidBody2D and set_linear_velocity for movement.

Well, yes, after holding the key down for a few seconds it is as though the input is forgotten and tossed to the side of a road, like an empty soda can.  However, there is still a slight "hiccup" which seems laggy to me.  Restarting my computer, however, removed the lag but didn't fix the previous issue of input being forgotten. I wonder if it is, perhaps, another Windows-related issue, much like the jitter with 2D physics objects?

Sounds like the button press is handled as a one-of event? Hence why danjo's example of input state-machine might work better/well? Just to be clear, I haven't tested. This is just me making guesses based on what has been said in this thread so far.

Ahh, I see the issue. Yes, input events are events, not states. They only fire once, not every frame. Try putting a print statement after each [tt]if event.is_action . . .[/tt]. You should see it print once, the instant you press or release the button.

I've been playing with a rigidbody character, so it's a little bit different, but the general setup would be pretty much the same. I'm doing something like this:[code]const s = 9000 # movement force per secondvar speed = 0.0 # current speedconst maxspeed = 700func input(event): if event.is_action_pressed("right"): right = true if event.is_action_released("right"): right = false if event.is_action_pressed("left"): left = true if event.is_action_pressed("left"): left = truefunc process(delta): speed = get_linear_velocity().x if right: if speed < maxspeed: apply_impulse( Vector2(0, 0), Vector2(delta s, 0)) if left: if -speed < maxspeed: apply_impulse( Vector2(0, 0), Vector2(delta -s, 0)) else: # if no keys are pressed, apply a damping force. apply_impulse(Vector2(0,0), Vector2(get_linear_velocity().x get_mass() damping, 0)) [/code]

Ah, Ross you are my hero!I don't know why I didn't think about doing it that way. As you said, I was just overcomplicating it (I tend to do that A LOT when I feel I am not understanding something). Thank you for the clear example, and also explaining where my error was.  8)

7 years later