0
\$\begingroup\$

I have this coroutine that waits for the player input to drop out of a while loop as well as some if statements that expect input as well. However the Input.KeyCode doesn't work in the coroutine, or rather just returns false, even if I press the right key...

I checked it in the normal FixedUpdate and there it works.

There must be a simple thing I yet don't understand about coroutines.

private IEnumerator TabThroughPotentialSoldiersRightCoroutine()
{
    Debug.Log("InCoroutine!");
    while (!Input.GetKeyDown(KeyCode.Return))
    {
        Debug.Log("InWhile!");
        if (Input.GetKeyDown(KeyCode.Tab))
        {
            Debug.Log("potentialAttckGroupMembers: " + potentialAttackGroupMembers.Count);
            if (potentialAttackGroupMembers.Count > 0)
            {
                attackGroupRight.Add(AI.GetClosestEnemyGameObject(potentialAttackGroupMembers, GameObject.Find("MC")));
                potentialAttackGroupMembers.Remove(AI.GetClosestEnemyGameObject(potentialAttackGroupMembers, GameObject.Find("MC")));
                Debug.Log("Add to attackGroup: " + AI.GetClosestEnemyGameObject(potentialAttackGroupMembers, GameObject.Find("MC"))); 
            }
        }
        
        if (Input.GetKeyDown(KeyCode.Tab) && Input.GetKeyDown(KeyCode.LeftShift))
        {
            if (attackGroupRight.Count > 0)
            {
                attackGroupRight.Remove(AI.GetClosestEnemyGameObject(attackGroupRight, GameObject.Find("MC")));
                potentialAttackGroupMembers.Add(AI.GetClosestEnemyGameObject(attackGroupRight, GameObject.Find("MC")));
                Debug.Log("Remove from atckGroup:" + AI.GetClosestEnemyGameObject(attackGroupRight, GameObject.Find("MC")));
            }
        }
        yield return new WaitForEndOfFrame();
    }
    potentialAttackGroupMembers.Clear();
}
\$\endgroup\$
3
  • \$\begingroup\$ Have you tried to move GetKeyDown in the Update method and replace it in the coroutine with a bool? GetKeyDown returns true only in a specific point in time during the engine loop. \$\endgroup\$
    – Nikaas
    Jun 24, 2021 at 10:29
  • \$\begingroup\$ @Nikaas Thanks that worked. But it seems rather unclean because the Update method runs the whole game and looks at the ìf` statement. It would be kind of weird if that´s the optimal way. \$\endgroup\$
    – Werner
    Jun 26, 2021 at 11:24
  • \$\begingroup\$ The update method is the right place. Just move it into its own function, and call it from the update method. \$\endgroup\$
    – Evorlor
    Mar 21, 2022 at 4:11

2 Answers 2

1
\$\begingroup\$

The doc for Input.GetKeyDown says that it returns true during the frame. But your coroutine is working after the frame has ended due to: yield return new WaitForEndOfFrame();

So you need to change to something like this:

yield return null;

In that case your coroutine will wait until next update moment during next frame. That should help.

Also it looks like that there is another problem in your code:

if (Input.GetKeyDown(KeyCode.Tab) && Input.GetKeyDown(KeyCode.LeftShift))

Probably your intention with this code was to do something when both LeftShift and Tab keys has been pressed. But that code won't work as you expecting. The problem is the same GetKeyDown will return true only during the frame. That means that code would work only in case when both keys has been pressed in the same frame (moment), that probably very difficult to achieve if possible. So you should change this line to something like this:

if (Input.GetKey(KeyCode.LeftShift) && Input.GetKeyDown(KeyCode.Tab))

According to the doc GetKey will return true while the user holds down the key identified by name. So it should work as you need.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Note that the modified code will work if the player holds shift then presses tab. If they hold tab then press shift, that input will still get missed. \$\endgroup\$
    – DMGregory
    Mar 21, 2022 at 11:49
  • \$\begingroup\$ Probably another if like if (Input.GetKey(KeyCode.Tab) && Input.GetKeyDown(KeyCode.LeftShift)) will help. \$\endgroup\$
    – ChessMax
    Mar 21, 2022 at 13:22
-1
\$\begingroup\$
yield return new WaitUntil(() => Input.GetKey(KeyCode.Return));

Try this instead of while.

Another thing I tried was changing "GetKeyDown" to just "GetKey", and that seemed to work.

\$\endgroup\$
1
  • \$\begingroup\$ yield return new WaitUntil(() => Input.GetKey(KeyCode.Return)); Doesn´t seem to work because it just runs one time through and waits for the player Input but I need the coroutine to constantly check the other if statements. GetKey() does work but it returns true for every frame I hold the button wich is very often. GetKeyDown() would only return one true if the Key is pressed. \$\endgroup\$
    – Werner
    Jun 23, 2021 at 19:49

You must log in to answer this question.

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