Help a beginner, how to store a value until key release?

What i’m trying to do is to accumulate value while key is being held, and then stop accumulating once key is released, I’ve wrote this code but it does not work apparently --without errors though-, I cannot see where I made a mistake, im trying to do something like a cannon, where the force increases the longer u hold down a key.
Here is the code: // If spacebar is held down, power increases each frame, if getkey is not spacebar, add force to object.
Here is the code:
public class PlayerMovement : MonoBehaviour
{
public Rigidbody Player;
public float power = 20f;
// Update is called once per frame
void FixedUpdate()
{

if (Input.GetKey(KeyCode.Space))
{
power += 10 * Time.deltaTime;
if (!(Input.GetKey(KeyCode.Space)))
{
Player.AddForce(0, 0, power * Time.deltaTime);
}
}
}
}

I ALSO TRIED IT WITH WHILE LOOP:
public class PlayerMovement : MonoBehaviour
{
public Rigidbody Player;
public float power = 20f;
// Update is called once per frame
void FixedUpdate()
{

while (Input.GetKey(KeyCode.Space))
{
power += 20 * Time.deltaTime;
if(!Input.GetKey(KeyCode.Space))
{
Player.AddForce(0, 0, power * Time.deltaTime);
}
}

}
}

Based on your code I think you have a fundamental misunderstanding about how Update() and Input works in Unity.

Every frame, Unity is going to run your Update() method one time. During that frame, all input data is the same for the entire frame and the entire Update method. In your code you are checking for Input.GetKey(KeyCode.Space), and then INSIDE that if statement, you are checking for !(Input.GetKey(KeyCode.Space)). The negated version will never be true. Remember your entire update method is run once every frame and during the method, the values in Input will not change.

What you should do is check for Input.GetKeyDown(…) and Input.GetKeyUp(…) in separate if statements to detect when the key is pressed and released.

3 Likes

Please use code tags: https://discussions.unity.com/t/481379

Everything @PraetorBlue writes above is spot-on.

GetKeyDown() will NOT work reliably in FixedUpdate() either.

You need to gather input in Update() and act on it there, or if you must do physics, act on the input (store it in temporary variables) in FixedUpdate(), which is only for physics-facing stuff.

Adding one more tidbit, here is some timing diagram help:

https://docs.unity3d.com/Manual/ExecutionOrder.html

3 Likes

Ah good catch @Kurt-Dekker I didn’t notice op was using FixedUpdate for input capture as well!

3 Likes

Hey man, a beautiful explanation, thanks :). so should I do two separate if statements for getkeyup/down?

ty for notice :), well its input and physics at the same time, what should I do?

Read input in Update(), store the input in temporary variables, act on the input in FixedUpdate(), as I noted above.

3 Likes

Yes, but like @Kurt-Dekker was saying, FixedUpdate doesn’t run every frame so it’s better to capture the input in Update, store it in a bool variable, then consume that in FixedUpdate by reading the bool and setting it back to false.

2 Likes

In your case I would do all the “hold and charge” stuff in update, and only save the AddForce part for FixedUpdate, after the key is released.

1 Like

Hey guys I appreciate the help from both of you, thanks!!, my code worked now I can launch a cannonball lol
I know the code might be a bit messy but here it is:

public class PlayerMovement : MonoBehaviour
{
    public Rigidbody Player;
    public float power;
    bool hold;
    bool charge;
    bool release;
    // Update is called once per frame
    void Update()
    {   
      
     if (Input.GetKey(KeyCode.Space))
        {
            power += 1000 * Time.deltaTime;
            Debug.Log(power);
            hold = true;
            }
        if(Input.GetKeyUp(KeyCode.Space))
        {
        charge = true;
  }
        if(hold == true && charge == true)
        {
        release = true;  
  }
            
            
        }
        void FixedUpdate()
        {
            if(release == true)
            {
                Player.AddForce(0, 10, power * Time.deltaTime, ForceMode.VelocityChange);
                hold = false;
                charge = false;
                release = false;
   }
  }

    
}
1 Like

Looks good to me! That’s exactly how to do it.

Also, the reason those close braces fail so often in code posted here is a combination of the VS/Mono editor handling copy/paste of code NOT as pure text (it uses some bastardization of rich text), the VS/Mono editor inconsistently handling tabs and spaces, and then the Javascript browser window on Unity forums failing to figure it out.

To avoid this, when you paste code into the window, use Paste-and-match-style, if your browser has it. At least it will be closer. :slight_smile: