Is Input detection ok to do in fixedupdate?

I’ve seen a few things where people say not to detect for input in fixed update because its less accurate etc. However I just ran some tests that say differntly. I ran a script with some big loops in them to get the FPS to around 2. I then tested input detection in both update and fixedupdate. I actually found that it was more responsive in fixed update, what I mean by this is that when in fixed update, it takes about 2 frames for it to register after you press a button. In update it takes about 3 frames after you press the button for it to register. So not only do keypresses always register in fixedupdate, they seem to be more responsive. Thoughts?

You should be shot for trying to run a game at 2 FPS, how can that be defined as fun? :slight_smile:

As I understand it the reason for using Update is that input data is changed every frame. So if you run two FixedUpdate cycles during one frame then the same input data will be read twice. On the other hand if you run two frames during one FixedUpdate then some input data will be missed. (In some cases this does not matter, jumping is one where this really shows)

The typical flow goes like this

  • Get input in Update
  • Apply changes to physics in FixedUpdate

But seriously, use a coroutine or something. There is no way you should accept a frame rate of 2.

Well FixedUpdate() is for physics but if the game was running at lets say 100fps there would be two calls to Update for every call to FixedUpdate
However if its running at say 30 frames per second it would mean that sometimes there would be more FixedUpdate calls then Update
Input detection would be okay to do but its not recomeneded because in FixedUpdate the input could possibly be missed.

You can’t use FixedUpdate to do input detection such as keypresses. FixedUpdate does not necessarily fire every frame, so input will be lost sometimes. You can potentially do axis input, though, since holding down a key will return a value continuously over many frames. The *Up and *Down events are true only for a single frame though.

I’ve experienced similar issue with responsiveness. I’m doing a very fast-paced game, so that matters a lot in my case.

I tested WinAPI’s GetKeyState() against saving input state in Update() and checking it in FixedUpdate() and got similar results to OP’s - the Update()'s saved data was delayed if Update()'s frequency was similar to/lower than FixedUpdate()'s. That resulted in noticeable lag even at 60fps + v-sync. In that case, using Input in FixedUpdate() gave me better time resolution, which matters a lot in fast-paced games.

I say it’s perfectly valid to check the input in the FixedUpdate() if you need better accuracy/responsiveness but you’re OK that you might miss some input data (like user pressing and quickly releasing a button between frames). It works well for platform-like movement even if “Every second v-blank” option is enabled.

However, we should remember that Up()/Down() thingies will still require Update() to function properly. Again, you can roll your own up/down mechanism based on current button’s state if you need similar responsiveness and if you’re OK that you can miss too-quickly-pressed buttons.

Also I found out that putting all logic in Update() and limiting the framerate with Application.targetFrameRate gave me even better feel than fiddling with FixedUpdate() (it’s probably because Update() depends on render speed, FixedUpdate() doesn’t, so the rendered image might still be one frame late if the desync happens), so maybe that would be better in your case.

So, we shouldn’t get too religious about those things in case of GetButton(), GetAxis() etc. It just depends on the case.

The code I used in the test (it’s a body of MonoBehaviour class used, I just removed the unrelated stuff). Note that I tested it with “Every second v-blank” quality setting:

            [DllImport("user32.dll", SetLastError = true)]
            static extern Int16 GetKeyState(UInt16 virtualKeyCode);
    
            bool test = false;
    
            void Awake() {
            }
    
            void Update() {
                test = GameInput.GetAxisRaw("Horizontal") < 0;
                Debug.Log("UPDATE");
            }
    
            void FixedUpdate() {
                const ushort VK_A = 0x41;
    
                Debug.Log(GetKeyState(VK_A) + " " + test + " " + (Input.GetAxisRaw("Horizontal") < 0));
                Debug.Log("FIXED_UPDATE");
            }

The result:

alt text

The actual movement’s feel of responsiveness conforms the test results.

Please try it yourself and share results.

It just doesnt work
using Up = Input.GetButtonDown(“verticalUP”); in update()
gives less delay than using it in fixedpdate()

but it just gets weird it doesnt always fire when the player moves foward and whatever.

FixedUpdate is overkill. Good frame rate is much faster than human fingers.

Even if Unity updates the results of the Input class faster than your current frame rate, you should never waste processor power on those extra cycles because you’ll never need them.

Your frame rate should never drop below 30fps for smooth play. At 30fps, you’re clocking 33 milliseconds per frame. Human reaction to visual stimuli averages around 200 milliseconds, so a passing frame rate is about 6X faster than your user’s reaction time.

The Update Loop will keep up with the average human reaction time at about 5fps, but your game will look terrible if it ever gets that slow. The Update loop is much more than you need for clean input as long as you’re at a good frame rate.

Don’t try to catch GetKeyDown/GetKeyUp/GetButtonDonw/GetButtonUp events in FixedUpdate as it will be quite often skipped. E.g. to check for jump in FixedUpdate method is bad idea.
Also Update is called every frame and you usually want input detection tightly related to the current character or controlled object position. So it’s reasonable to check input in Update as in this way you can be sure the movement is related to the current position in the current frame.
FixedUpdate is not frame related and it might be called for instance once per 3 frames (it depends on the configuration and frame rate of course) or vice versa.