I made a character controller script that is at a point where it is working the way I intend - mainly being able to have momentum during a jump and to be able to slightly move while mid-air. However, I wrote it originally using the FixedUpdate() method, then later came to realize that this is causing issues with stuttering and such and now understand that I should have used the Update() method instead.
When I simply change “FixedUpdate()” to “Update()” in my code, there are suddenly bugs that I can’t seem to figure out. With FixedUpdate() my player moved the way I intended, now the player continues to move in the jump direction even after it lands back on the ground (even with no input from me).
I just don’t understand how this happens when the only thing I’ve changed is the update method.
See my code below
Anything helps
Thanks.
If you’re not using physics, DO NOT USE FixedUpdate(). You are not using Physics that I can see above, so don’t use FixedUpdate().
Here is some timing diagram help to understand why:
It also looks like the above controller is derived from the original Unity CharacterController, which is now seriously bugged. The reason: you cannot call .Move() twice in one frame (like 55 and line 60 above) as it will break your ground sensor.
I wrote about this before: the Unity example code in the API no longer jumps reliably.
I reported it to Unity via their docs feedback in October 2020. Apparently it is still broken:
Here is a work-around:
I recommend you also go to that same documentation page and ALSO report that the code is broken.
When you report it, you are welcome to link the above workaround. One day the docs might get fixed.
Some more info on the lines of what @Kurt-Dekker is saying. The purpose of FixedUpdate is so you can run physics related code immediately before the actual physics engine update takes place. If you’ve got code which doesn’t involve physics inside FixedUpdate, it almost always is in the wrong place.
FixedUpdate is called on its own schedule, without regard for frame updates. Depending on frame rate, it might be called multiple times between frames, or 0 times between frames. Since it might not be called between frames, it is also a terrible place to put any input related code, because that code will miss input on any frame where FixedUpdate isn’t called.
The higher the frame rate, the more likely FixedUpdate isn’t called between any individual frames. The lower the frame rate, the more likely you’ll have FixedUpdate called multiple times between any individual frames.
I don’t necessarily consider it a no-go. If the code is highly dependent on results from FixedUpdate, then it follows to keep the codebase cleaner by also doing reasoning about it in FixedUpdate. This matters more for things like Contact Modification character controllers and similar. If a flag is set in Update and you did it there, it could actually lead to bad or incorrect results as you will want to run the responding code the same amount of times.
So a spike in the framerate or interruption can cause Physics to run more times than Update does, albeit briefly and it’s that situation in which the classic advice becomes the wrong advice.
Obviously this is a niche case as most people are not depending that tightly on the results of a simulation step. I just felt it worth pointing out there’s one case for it.