- Home /
Input and applying physics, Update or FixedUpdate?
Hello, this question has been asked a couple of times. But I'm seeing alot of conflicted answers.
I want to add velocity to an object when a gamepad button is pressed.
if( Input.GetButtonDown ("A_" + controller.ID) || Input.GetKeyDown( KeyCode.UpArrow ) )
{
if( grounded || doubleJumpCount < doubleJumpCounterMax )
{
float jumpPower = jumpPush;
rigidbody2D.velocity = new Vector2( rigidbody2D.velocity.x, jumpPower );
jumpTimer = jumpTimerMax;
doubleJumpCount++;
anim.SetBool("jump", true );
}
}
else
{
anim.SetBool("jump", false );
}
if( Input.GetKey( KeyCode.UpArrow ) || Input.GetButton ("A_" + controller.ID) )
{
rigidbody2D.velocity += new Vector2( 0f, jumpSustain );
}
When doing this in the Update, I get different results with different framerates. When doing this in FixedUpdate Input.GetButtonDown sometimes returns false when it's not supposed to.
The same question has been discussed here, but it seems like a very messy solution to keep track of all the input manually.
Most of the answers I've read on here say that polling input in FixedUpdate should never be done. This sample on the unity3d website does poll input in the FixedUpdate though;
I'm getting the best results in the Update right now. I might be able to get consistant results on different framerates when I apply deltatime. But I want to avoid applying physics in the Update where it doesn't really belong.
Put input code in Update(), move your physics to FixedUpdate()
Answer by tanoshimi · Feb 08, 2015 at 09:55 PM
This is a confusing and often misunderstood area. As a general rule:
Input should be in
Update()
, so that there is no chance of having a frame in which you miss the player input (which could happen if you placed it in FixedUpdate(), say).Physics calculations should be in
FixedUpdate()
, so that they are consistent and synchronised with the global physics timestep of the game (by default 50 times per second).Camera movement should be in
LateUpdate()
, so that it reflects the positions of any objects that may have moved in the current frame.
However, there are always exceptions to these, and some experimentation may be required to get what works for you in a given scenario.
That's a great answer to this question! Thank you for explaining these three different update methods! :) Definitely super helpful!
Answer by calebgray · Feb 08, 2015 at 09:14 PM
tl;dr: FixedUpdate will be called 0..n times per frame. Update will be called once (after physics are updated) per rendered frame. For perfectly accurate input you should honestly check for input in both places. If you're not trying to replicate the per pixel perfection of Mega Man X's input and collision detection, then you're perfectly safe putting everything in Update. Just know that you will be losing a frame of physics by doing so.
Do not let anyone tell you that not using FixedUpdate1 is a good idea. FixedUpdate is fired before physics calculations... this means that if you put your input code there, the player will see the reaction to the inputs on the SAME frame, not the next one. This becomes significant at low frame rates. (Especially consider 30 FPS capped mobile devices.)
Scenario One: You've created a game and want to have an NPC pacing left and right, up and down a flight of stairs. You've put your pacing code in Update and everything works perfectly... until your CPU is hit with a surge of other things to do from another process. Your FPS drops down to 2, even just for a moment, but it's in that moment that your physics breaks down. If you've implemented your "ascend stairs" logic in Update using raycasting, you'll notice that your NPC didn't quite move the same way that they had been while your FPS was 60. This is because you've taken away Unity's ability to give you accurate and "in reaction to" physics events (OnCollision*).
Scenario Two: The playable character is falling (because, you know, gravity)... we come to the frame where our character "lands on the ground," great! But wait! Look out! An incoming projectile which you literally only have one frame to dodge! You've decided to use FixedUpdate, but you have a boolean flag so that you only process user input once per rendered frame. Once again, this is a bad idea. You WANT what I've seen others call "double input" because it isn't on the frame that the character lands that gravity is applied, but rather the frame before! The first hit to FixedUpdate if (Button.Jump && IsGrounded) Jump()
will fail... then the physics will be applied, collisions will occur, and FixedUpdate might be called again (possibly several times!) and/or Update will be called. Technically, we should check if the character is both 1) grounded, and 2) attempting to jump in both FixedUpdate and Update... this way when THIS frame is rendered, the player will see that their character did in fact land on the ground, and is already beginning the "jump!" animation.
I threw together a simple MonoBehavior2 to show the order that Unity calls these events to reiterate the importance of using both FixedUpdate and Update for input/physics changes. See the comments for the difference between fired events at different frame rates.
I have tried inputs in FixedUpdate and more often than not they are quite buggy.
Continuous Input works, like accelerometer, but polling for buttons often results in missed input and strange delays. This especially true of ButtonDown routines.
Physics, however, must always be performed in FixedUpdate. To that note, adding anything other than Physics to FixedUpdate is often a bad idea as placing too much code in there can turn out bad:
FixedUpdate gets culled in low framerate situations (This is also a reason why input is bad there).
FixedUpdate can often get called many times more than Update, so heavy routines will have a detrimental effect, often attempting to execute heavy routines many times per frame.
Heavy FixedUpdate will cause bad Physics behaviour.
Just some things to consider.
I think Input should be on Update. Putting it in FixedUpdate causes problems for me.
"FixedUpdate is the first event that is fired" - that sentence doesn't make sense: FixedUpdate is fired according to the physics loop, which is not synchronised to the main game loop. So there may be zero, one, or more Update()s fired between each FixedUpdate() (and vice versa).
Events Executions at 2 FPS: (I could literally watch one frame render with all of my characters move before $$anonymous$$e did while holding a key down by using "Update." $$anonymous$$any mobile devices cap at 30 FPS, this means there will be a noticeable lag between input and character reaction.) FixedUpdate FixedUpdate FixedUpdate FixedUpdate FixedUpdate FixedUpdate FixedUpdate FixedUpdate FixedUpdate FixedUpdate FixedUpdate FixedUpdate FixedUpdate FixedUpdate FixedUpdate FixedUpdate FixedUpdate Update LateUpdate
And at ~360 FPS: (I was still able to control my character with my gamepad, keyboard and mouse...I was able to jump and move around. I stand corrected, FixedUpdate doesn't always fire.) FixedUpdate Update LateUpdate Update LateUpdate Update LateUpdate Update LateUpdate Update LateUpdate Update LateUpdate Update LateUpdate
So, it looks like a "perfect" implementation will always end up being a hybrid of both FixedUpdate and Update. I'll correct my answer.
Answer by ImpOfThePerverse · Sep 26, 2017 at 07:38 PM
I have a hoverboard simulator where the board and player rotate about the Z axis in response to mouse input, with the turn radius being determined by the resulting bank angle. The rotation is governed by a torque being applied in FixedUpdate. I was also reading the mouse input during FixedUpdate, but occasionally the physics would hiccup, and in addition to a hitch in the framerate, I'd get a sudden rotation of 45+ degrees that rendered it unplayable. Moving the mouse input code to Update fixed the problem (there's still the occasional framerate hitch but the sudden rotation errors are gone.)
Your answer
Follow this Question
Related Questions
Supplying Input from Update To FixedUpdate 1 Answer
Mouse Input for RayCast - Update or FixedUpdate 1 Answer
How do I pass an input in Update() to FixedUpdate() for Physics movement? 2 Answers
Why Do Inputs Have to Been in Update (Rather than FixedUpdate)? 3 Answers
Not registering input when checking input in Update and using input in FixedUpdate 1 Answer