In my game, currently, the jump button also serves as the confirm button, and I’m planning to add more advanced control mappings that would allow for primary and secondary bindings. There is however a problem with the pause screen, which is described in the title. I assume if I were to map the confirm button to a key that does something else, like attacking, the player character would do that other extra action when unpausing. Currently I have this problem sorta solved by having await get_tree().create_timer(0.01).timeout before actually unpausing the game, but recently I learned that awaiting isn’t the best way to do stuff and also timers like these can be unreliable. So like… is there a better way to solve this problem?
This is where _unhandled_input could help, if you can place jumping inside that function instead. Otherwise adding a short transition like a fade-out after unpausing or even waiting one frame await get_tree().process_frame isn’t so bad.
First one doesn’t work for me at all, second one kinda works arbitrarily, sometimes it does, other times it doesn’t. As for fadeouts, I don’t even know how it would work in my game because the paused game is literally the game screen but darkened, with the pause menu slapped on top. There kinda isn’t anywhere to put the fadeout, unless I’m misunderstanding something
Depends on how you are handling the pause menu too, if you are using a Button then _unhandled_input should work, otherwise you will have to consume the input manually with accept_event() on Control node or get_viewport().set_input_as_handled() on other nodes. Eitherway _unhandled_input should be the go-to input processing function because it allows these kinds of interrupts to prevent an input from walking all the way up the tree.
I presume your pause menu is a scene, you could add an AnimationPlayer to fade out the “darkened” game screen, then unpause the game once it’s finished animating.
Yes I am using a Button so why the hell doesn’t it work? There is a possibility that it could be because I have my own CustomButton class that inherits from BaseButton, but like, I didn’t override any press functions, so I don’t even know
Okay so a combination of accept_event() and putting my movement inputs into _unhandled_input seems to fix this problem but it creates a new one: for whatever reason, my character doesn’t jump as high anymore compared to when the inputs were in _physics_process??? Why is that?
So here’s basically the entirety of the inputs func
func movement_inputs() -> void:
#region Jumping
if Input.is_action_just_pressed("jump"):
if !jumped:
if is_on_floor() or coyote_timer > 0:
if !Input.is_action_pressed("ui_down"):
jump_buffer_timer = JUMP_BUFFER_TIME
else:
set_semisolid_fallthrough(true)
elif PlayerStats.energy > MIN_GLITCH_ENERGY and jump_buffer_timer <= 0:
glitch()
if is_on_floor() and jump_buffer_timer > 0:
velocity.y = -jump_force
jump_buffer_timer = 0
# glitch prep
if Input.is_action_just_released("jump") and !jumped:
jumped = true
if velocity.y < -jump_height:
velocity.y = -jump_height
#endregion
#region Interaction
if Input.is_action_pressed("ui_up") or Input.is_action_pressed("ui_down"):
var collider: Area2D = $NpcDetectionRay.get_collider()
if Input.is_action_just_pressed("ui_up"):
if is_on_floor():
ladder_buffer_timer = LADDER_BUFFER_GROUND
else:
ladder_buffer_timer = LADDER_BUFFER_AIR
if (Input.is_action_pressed("ui_up")
and (collider and collider.get_collision_layer_value(8) == true
and collider.overlaps_area($InteractBox))
and (!is_on_floor() or (is_on_floor() and ladder_buffer_timer > 0))):
get_on_ladder(collider)
if Input.is_action_just_pressed("ui_down"):
if !is_on_floor():
set_semisolid_fallthrough(true)
if collider and collider.get_collision_layer_value(9) == true:
get_on_ladder(collider)
if is_equal_approx(input_vector.x, 0) and !looking_around:
_enable_looking_around()
if Input.is_action_just_released("ui_up") or Input.is_action_just_released("ui_down"):
_disable_looking_around()
if Input.is_action_just_released("ui_down"):
set_semisolid_fallthrough(false)
#endregion
Normally it sits at the very top of state_move(), which is in _physics_process and mostly takes care of the animations:
If moved to _unhandled_input, it reduces jump height very slightly, barely noticeable until you need to jump on a 4-tile-tall platform and suddenly you can’t anymore
My gods, why does it have to be so hard with so many redundant flags? How would this flag be any different from simply checking if the tree is paused or not?
It’s not different, although you typically don’t want to pause the tree when the game is paused. Some processing always needs to happen. Flags are bread and butter of programming. A typical game may have hundreds of them. Learn to apply them with confidence to solve simple problems like this.
You can likely solve this by setting things up to play nice with engine’s input handling order, but a mutual-exclusion flag is bulletproof and will work regardless of how the input is handled.
The actual jump force happens on release, can you move only the pressed part to _unhandled_input? That should edit the velocity exactly the same, thus the same jump height.
I do strongly disagree with normalized on writing your own paused variable, the engine’s works fine and handles processing certain things and their children through their process_mode property.
It doesn’t have to be called paused. It can be called player_input_enabled or whatever it actually switches.
I’d personally handle this solely via engine mechanisms but when people have problems with understanding simple switching logic, implementing things like this is good exercise. So I’d recommend OP makes it work with a custom flag, and then we can discuss the finer points of how to handle it elegantly in accord with engine’s input hierarchy and node processing.
I actually do have one like that, it’s called allow_input and currently serves to prevent player from moving during screen transitions when the game technically isn’t paused (I mean it’s paused during most of them but not when transitioning to a stage, for the stage title card to be able to pause correctly)
I think they’d end up with their initial solution but with player_input_enabled instead of paused
I also don’t think it’s great practice to make a bunch of flags; They do already have quite a few, and superfluous flags are something state machines are supposed to reduce.
If a delay is desired then it should come from an animation, I don’t think it’s a particularly bad solution in this case, especially as I’d recommend the animation any ways. snowystoat’s on the right track by detecting random await create timers as a nasty code smell. There is probably a route re-working your inputs to feed through the input handling system, but with the state machines splitting it sounds messy and yet more annoying to build on.
The problem likely happens because the flag condition check happens on the same frame the flag is switched, only a bit later. Changing the value deferred would avoid that and need for any awaits/timers.
I don’t think a delay is really desired in my case
I tried doing this and while it does restore max jump height it also makes the jump floatier overall (as well as ruins my nicely structured code where the rest of the function takes care of the animation and then BAM there’s an input bit smack dab in the middle)
I hoped this would work but no, he still jumps every now and then even if it’s set deferred
Interesting, can you share how this code looks? I can’t imagine it changing jump height that much, I assumed the slight reduction in height would be from gravity being applied after setting velocity.y for one frame, just a slight operation re-ordering error. You’re not applying gravity as part of the input function right?
Okay nvm I tried it again and it works just fine, maybe I accidentally pasted it in the wrong place the first time
Okay so currently I have both setting pause deferred and the inputs func moved to _unhandled_input. This seems to have fixed the problem. Thanks a ton everyone