0
\$\begingroup\$

I just wanted to fact check myself on a scenario where the player may be locked out of input.

With this example, there is a chance that the player's input will not be received if they happen to press the button during WaitForSeconds(), correct?

private IEnumerator CheckForButton()
{
    // Check for player input at the beginning of the method
    if (GameEngine.Instance.InputController.playerActions.Menu.Select.WasPressedThisFrame())
        {
            // do stuff
            yield break;
        }
        
        // Is the player is locked out of input here?
        yield return NewWaitForSeconds(2f)
}

To avoid that, would using a loop as a timer and checking for player input like this be a more correct way?

private IEnumerator CheckForButton
{
    // Check for input at the beginning of the method
    if (GameEngine.Instance.InputController.playerActions.Menu.Select.WasPressedThisFrame())
    {
        // do stuff
    }
    float t = 0;
    float targetTime = 2f;
    
    // Also check for input while the timer counts down
    while(t < targetTime)
    {
        if (GameEngine.Instance.InputController.playerActions.Menu.Select.WasPressedThisFrame())
        {
            // do stuff
            yield break;
        }
        t += Time.deltaTime;

        yield return null;
    }
}

To be more concise, will the player be locked out of input if they press a button during WaitForSeconds()? Thanks!

\$\endgroup\$
3
  • \$\begingroup\$ This looks like something you could test for yourself, no? \$\endgroup\$
    – DMGregory
    Commented Feb 9, 2023 at 1:49
  • \$\begingroup\$ Well, the reason I asked was because I noticed that some of my button presses weren't going through. I think that this is the reason why, but I wanted to make sure. I also wanted to make sure that my workaround was a solid solution! \$\endgroup\$ Commented Feb 9, 2023 at 1:53
  • \$\begingroup\$ If you have a workaround, post it as an answer, that would help others, if it is correct, and give hints to what might be wrong. \$\endgroup\$
    – user122973
    Commented Feb 9, 2023 at 2:31

1 Answer 1

3
\$\begingroup\$

Yes, that can definitely cause you to miss the input. Since you are manually checking wasPressedThisFrame, the only way to guarantee that you won't miss it is to run that line of code every frame.

The first snippet you posted does not do that; instead, it checks only once, then it reaches the yield return NewWaitForSeconds(2f) line, where it will stay until 2 seconds have passed, and then exits the function.

The other option, using a loop with yield return null, will work (yielding null just causes the execution to resume at the start of next frame, so there is no frame when the coroutine is just stopped). As a very minor point, with the code as written there is no need to check for input outside of the loop, as the first iteration of the loop is executed right away anyways.

Also, since I think you are using the new Input System, a potentially "better" solution (subjective, really) would be to use action callbacks with a delegate. Something like this, more or less:


private void DoStuff(InputAction.CallbackContext ctx)
{
    //process the input here
}
private IEnumerator CheckForButton()
{
    GameEngine.Instance.InputController.playerActions.Menu.Select.performed += DoStuff;
    yield return NewWaitForSeconds(2f)
    GameEngine.Instance.InputController.playerActions.Menu.Select.performed -= DoStuff;
}

And if you don't want to create a separate function for DoStuff, it can even be a local lambda:

private IEnumerator CheckForButton()
{
    System.Action<InputAction.CallbackContext> DoStuff = (_)=>{/* process the input here*/};
    GameEngine.Instance.InputController.playerActions.Menu.Select.performed += DoStuff;
    yield return NewWaitForSeconds(2f)
    GameEngine.Instance.InputController.playerActions.Menu.Select.performed -= DoStuff;
}

```
\$\endgroup\$
2
  • 1
    \$\begingroup\$ Just remember to also remove that event handler when the coroutine gets interrupted. Which can happen explicitly by calling StopCoroutine / StopAllCoroutines, or implicitly by the destruction of the GameObject hosting the coroutine. \$\endgroup\$
    – Philipp
    Commented Feb 9, 2023 at 9:09
  • \$\begingroup\$ Thanks for clarifying, PepeOjeda! \$\endgroup\$ Commented Feb 9, 2023 at 17:03

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .