What would happen (in practical terms) when a GameObject with a Rigidbody is moved using Update?

Hi to everyone.
I’m trying to understand (using practical examples) why Rigidbody methods should NOT be called from Update. Below is a code that follows the recommendation of putting Rigidbody methods inside FixedUpdate.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Movement : MonoBehaviour
{
Rigidbody rb;
float impulse = 6f;
bool jump;
// Start is called before the first frame update
void Start()
{
rb = GetComponent();
jump = false;
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
jump = true;
}
}
private void FixedUpdate()
{
if (jump)
{
rb.AddForce(0f, impulse, 0f, ForceMode.Impulse);
jump = false;
}
}
}

Let’s assume the following sequence of method calls (Ux is the x-th call of Update and Fx is the x-th call of FixedUpdate):

… -----U1----F1------U2---------------F2------------U3-----------F3----- …

If the player pushes the space bar in U1, GetKeyDown(KeyCode.Space) will return true and jump will be set to true. After that, in F1, GameObject will receive an impulse and jump will be set to false. When U2 is called, GetKeyDown(KeyCode.Space) will not return true, even though the player has not release the space bar yet. So, jump will remain equals to false and the GameObject will not jump in F2.
Now, let’s modify that code a little:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Movement : MonoBehaviour
{
Rigidbody rb;
float impulse = 6f;
// Start is called before the first frame update
void Start()
{
rb = GetComponent();
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
rb.AddForce(0f, impulse, 0f, ForceMode.Impulse);
}
}
}

I don’t see how this latter code can cause errors when we assume the same sequence of method calls mentioned for the former. In that sense, can anyone provide an alternative sequence of method calls showing how the latter code isn’t good enough? Alternatively, can anyone show a simple code that shows how dangerous is to put a rigidbody method inside Update? I’ve seen that procedure can cause imprecise physics simulation, but I haven’t seen any code followed by a sequence of method calls showing that.
Thanks in advance!

First, please put your code in code tags as explained here: https://discussions.unity.com/t/481379

And the reason you shouldn’t move your RigidBody in Update function is because physics has a separate world where all physics simulated. This world is updated right after the FixedUpdate calls but not after Update calls.
You can find under the label of “internal physics update” on this chart: https://docs.unity3d.com/Manual/ExecutionOrder.html

This means if you update your RigidBody in Update method, the physics won’t know about it until the next internal update, which may or may not happen in even the next frame.
Remember: physics is running on a different clock (by default 50 times a second and in a different manner), so during a render frame it is possible that the physics update doesn’t happen or happen more than once.

This makes your physics simulation unreliable.

Thanks, Lurking-Ninja!
So, if we call AddForce() in Update, that method will be called only on the next call of FixedUpdate, right?

No. The call itself will happen right away, but you won’t see the change until the next internal physics update. Which may or may not happen in the next frame (instead of the current frame as supposed to).

Ok, let me repost the latter code:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Movement : MonoBehaviour
{
    Rigidbody rb;
    float impulse = 6f;

    // Start is called before the first frame update
    void Start()
    {
        rb = GetComponent<Rigidbody>();
    }

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            rb.AddForce(0f, impulse, 0f, ForceMode.Impulse);
        }
    }
}

So, assuming the following sequence:
… -----U1----F1------U2---------------F2------------U3-----------F3----- …
If the player pushes de space bar in U1 he will see the jump only in U2, right?

Why exactly are you interested in doing things the wrong way? Do you want your game to malfunction?

It’s not super-complicated:

  • Gather the input in Update() and set a boolean if SPACE is pressed

  • In FixedUpdate(), if that boolean is true, DO the jump, then clear the boolean

That’s it. Here’s why:

Here is some timing diagram help:

Yes, if the FixedUpdate runs between U1 and U2, then you will see it in U2.

Don’t get me wrong, Lurking-Ninja. I’m asking you for that stuff because I’m a teacher who is learning how to make games in Unity and wants to be prepared for questions like:

  • Why is that wrong? Give me an example!
    The original code is the right way to do the things:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Movement : MonoBehaviour
{
    Rigidbody rb;
    float impulse = 6f;
    bool jump;

    // Start is called before the first frame update
    void Start()
    {
        rb = GetComponent<Rigidbody>();
        jump = false;
    }

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            jump = true;
        }
    }

    private void FixedUpdate()
    {
        if (jump)
        {
            rb.AddForce(0f, impulse, 0f, ForceMode.Impulse);
            jump = false;
        }
    }
}

What I’m saying is both versions will produce the same result taking if we have the same sequence of method calls below:
… -----U1----F1------U2---------------F2------------U3-----------F3----- …
Thus, I think I’m not using the best example to show how important is the recommendation of putting Rigidbody method calls in FixedUpdate. I think we agree with that, right?
As an additional comment, I teach Computer Networks - not game development. But it is a subject which I’m interested to learn and teach.
Thank you so much for your comments.

All of your example frame timings have a perfect sync of one Update and one FixedUpdate. That’s not how it works. Update runs every single frame, no matter what. FixedUpdate runs 0…n times per frame depending on the tick rate. So it could execute 0 times, or 1, 2, 3, even 4 times or more. FixedUpdate is also called before Update, so even your simulated 1:1 timings don’t actually line up.

Hi, GroZZIeR!
In fact, I know that. I’ve just put a 1:1 ratio for simplicity’s sake. I could use this sequence, instead:
… -----U1----F1----------F2----U2----F3-----U3- …
We have two calls to FixedUpdate between calls U1 and U2.
The point remains: to build an example that depicts how putting a Rigidbody method in Update could cause unreliable physics. We all know that if we applied AddForce in U1 its effects would only be visible in U2, right? Ok, but if we applied AddForce in F1, its effects would only be visible in U2 as well. So, why do I have to apply it in F1 instead of U1?
I know the answer, in general terms: because if we applied it in the Update method that would produce an unreliable physics. I know that by heart. But it’s not the case here in this example, right?
I’m simulating a skeptical student, gentlemen. Please, bear with me :slight_smile:

F1...U1....F2...F3...U2...F4...U3...
Always starts with FixedUpdate, that is called before Update. Again, visit the link we shared about execution order.

Yes, but visibility is just one part of the story, the other part is the calculation with it. In my example here, if you set something in Update (U1), you calculate with the same values in F2 and F3 and you only have the chance to change things in U2 which will propagate into the physics system in F4.
Meanwhile if you use FixedUpdate, you can change things in all Fx calls before the physics system calculates gravity, collisions, etc.