Using Update for Input Sensing and FixedUpdate for Physics Movement

I’ve seen a number of sources that state that anything physics-related should reside in the FixedUpdate method, whereas things like controller input should be placed in Update. Quite a beginner question here, but how do I access the inputs defined in Update in physics-related Methods in FixedUpdate? I have one method in Update called ‘GetInputs’, with a short list of variables, and a couple of methods in FixedUpdate pertaining to the movement of my character. Can anyone shed any light on the matter?

I believe it’s okay to read Input in FixedUpdate provided you avoid ‘Down’ and ‘Up’ functions like Input.GetKeyDown or Input.GetMouseButtonDown. The value returned by those functions is only true for the current Update() frame. FixedUpdate() and Update() can often be out of sync and so FixedUpdate() will sometimes miss the ‘Down’ and ‘Up’ moments/frames.

You can do a test that involves reading GetKeyDown in FixedUpdate and launching bullets across the screen. You’ll notice that you won’t be able to launch them as regularly as you can when doing the same test from Update().

You could always create your own GetKeyDown function that works reliably from FixedUpdate().

1 Like

Otherwise you just register the button press in a variable, or you calculate the resulting motion vector but only apply it during FixedUpdate. Strictly speaking this is not required but applying changes to physics during Update will make physics non-deterministic (not 100% sure though) and it will certainly be an issue for networked games. And last but not least there comes the deltaTime issues where you either don‘t apply it and get inconsistent input results or you do but there is a framerate hiccup and a high deltaTime causes input to exceed some „safe“ values for input - this can lead to inconsistent gameplay behaviour.

To put into code as to how you ‘bridge the gap’, you just work with fields local to the class itself, and use them in both Update and FixedUpdate.

For example:

public class Player : Monobehaviour
{
   private bool _willJump = false;
   
   private void Update()
   {
       if (Input.GetKeyDown(KeyCode.Space))
       {
           _willJump = true;
       }
   }
   
   private void FixedUpdate()
   {
       if (_willJump)
       {
           // jump
           _willJump = false;
       }       
   }
}
1 Like

That doesn’t appear to work for me. I can only access live input data from my controller if I declare and define the input within the very class that I intend to use it.

Think I’ve found where I’m going wrong here. Having created the member variables, when defining them in Update, I was typing the data type in (i.e. float), which probably caused it to create an entirely new variable that only exists within the context of the method I put it in, leaving the member variable itself unchanged at a constant 0, as it was when it was instantiated. Thanks for all the help! :wink: