Set RigidBody velocity in FixedUpdate() or Start()?

I’m developing a simple 2D game in Unity (balls hitting bricks), so i have a ball and i want to fire the ball to hit bricks, now to fire the ball i have to set Velocity on the RigidBody component attached to the ball’s GameObject.

There are two ways to do that:

Method 1:

Set the velocity inside the Start() method

private void Start()
{
    rb.velocity = direction * speed;
}

Method 2:

Write a FixedUpdate() method and put the statement in there. because:

Use FixedUpdate when using Rigidbody.(Unity Docs)

private void Start()
{
    _setVelocity = true;
}

private void FixedUpdate()
{
    if (!_setVelocity) return;

    rb.velocity = direction * speed;
    rb.angularVelocity = 0;
    rb.gravityScale = 0;
    _setVelocity = false;
}

But the thing is: i don’t need the FixedUpdate() method for anything else, because i only fire the ball once in its script’s lifespan, so after i fire the ball unity will continue to run the FixedUpdate()method and check for _setVelocity’s value and return (exit) every time because it will always be false after i shoot the ball the first time.

And this will happen every fixed frame-rate frame which is expensive i guess for just setting the velocity only once.

SO:

1. Is it expensive to have a FixedUpdate() method that checks for false value and returns every frame?

2. Which of the two methods performs better in this case?

Just set it in Start(). There is no benefit to putting that in FixedUpdate().

1 Like

It’s not a simple case of following some hard rule of “Use FixedUpdate when using Rigidbody” at all. The reason why that is recommended is because the physics system runs during the fixed update (after all those callbacks happen) so if you’re going to instruct changes continually to the physics system, it’s best to do it then and not (say) per-frame.

If you want to instruct a one-off change like setting the velocity of a rigidbody then go ahead and do it in the start if you want to. What wouldn’t make sense would be constantly changing the velocity per-frame as the physics doesn’t run per-frame.

Ignore those “rules”. Just know when stuff runs. In the case of physics, by default, it’s during the fixed update.

1 Like

Thank you very much for the explanation, i’m going to set the velocity in the Start() method then.

@MelvMay What about RigidBody2D.AddForce() can I also set it (once) outside of the FixedUpdate()?

You can call it whenever you like. Understanding what it does is all that’s important. It adds to the sum of forces that will be applied to the Rigidbody2D when the simulation runs then the sum is reset ready for the next simulation step.

If you call it per-frame then you’ll get forces which are a magnitude directly related to your frame-rate.

Nothing in 2D physics stops you from calling any methods or properties.

1 Like

Thanks

It just calls this: box2d/include/box2d/b2_body.h at cd2c28dba83e4f359d08aeb7b70afd9e35e39eda · erincatto/box2d · GitHub

Note it adds it to the sum to be used and nothing else i.e. “m_force”.

Here’s where it’s used in the integration step: box2d/src/dynamics/b2_island.cpp at cd2c28dba83e4f359d08aeb7b70afd9e35e39eda · erincatto/box2d · GitHub

1 Like

Great! this would help me understand how it works, one last investigation tho, the below code is when I want to disable and reset a gameObject after it finishes the exploding effect (to re-use it later):

            // Disable it
            gameObject.SetActive(false); // Disable the container
            firstPieceTransform.gameObject.SetActive(false); // Disable first piece
            secondPieceTransform.gameObject.SetActive(false); // Disable second piece
          
            // This is to stop the physics
            firstPieceRigidbody2D.isKinematic = true;
            secondPieceRigidbody2D.isKinematic = true;
          
            // Reset the rotation
            firstPieceTransform.rotation = Quaternion.identity;
            secondPieceTransform.rotation = Quaternion.identity;
          
            // Reset velocity
            firstPieceRigidbody2D.velocity = Vector2.zero;
            secondPieceRigidbody2D.velocity = Vector2.zero;
          
            // Reset angular velocity
            firstPieceRigidbody2D.angularVelocity = 0;
            secondPieceRigidbody2D.angularVelocity = 0;
          
            // Re-enable physics
            firstPieceRigidbody2D.isKinematic = false;
            secondPieceRigidbody2D.isKinematic = false;
          
            // Re-parent the effect to the destroyed cube (the initiator) after the destruction effect animation is finished and is not visible any more
            transform.SetParent(parentGameObjectTransform);
            transform.localPosition = Vector2.zero;
          
            // Re-position pieces
            firstPieceTransform.localPosition = Vector2.zero;
            secondPieceTransform.localPosition = Vector2.zero;

So I’m setting isKinematic = true before resetting the physics values even though the gameObject is now disabled, is this un-necessary?

When it’s inactive, there are no physics objects present in the physics engine at all so properties that are not serialized (volatile state) such as linear/angular velocities are lost anyway.

I’ve no idea why you’d set the body type either. That’s a serialized property, all it does when inactive is just reset the stored state.

“// Re-enable physics”
It seems like you’re trying to avoid the physics system seeing it by setting it to Kinematic? Doing that wouldn’t achieve that goal. What achieves that goal is the GameObject being inactive because there isn’t a physics body at all then.

Just set it to be inactive then before you activate it, set whatever state needs to be reset. Body-type doesn’t need to be reset because it doesn’t change. Lin/Ang velocity will be zero anyway.

1 Like

Thank you for the important information!

1 Like

To be clear here, when you activate a GameObject with a Rigidbody2D on it all the state you see in the inspector (stuff you can edit) is assigned to the physics body that is created. Also, the physics body pose is read from the Transform XY position and Z rotation.

The opposite of this is Rigidbody2D.simulated which doesn’t destroy the physics body, it just tells the physics engine to ignore this body, its attached colliders, joints and destroy any existing contacts etc. This is quick because it doesn’t involve destroying the body, collider, joint physics objects. It doesn’t however reset its state, it is, in the truest sense of the word, disabling it temporarily.

Using this, you would need to reset any state you were interested in because the physics objects are not destroyed. Deactivating the GameObject causes anything that has internal objects to be destroyed so at that point, it’s nothing more than a state container and should have no side-effects.

You mean setting Rigidbody2D.simulated = false ?
I see, but I actually have to deactivate the gameObjects after the animation is over, or I think I can only disable the container gameObject and leave the child “pieces” that have the RigidBody2Ds enabled and set their Rigidbody2D.simulated = false;

I think this would be cheaper?

(I’m trying to optimize the FPS and squeeze every frame I can get, and also prevent hiccups and sudden spikes in profiler)

I’m not telling you what to do in your situation, whatever that is, just explaining features that are available.

If you have to deactivate the GameObject then do so.

1 Like

What I meant by my last post is: Disabling a gameObject that has children with RigidBody2Ds on them (without disabling the children), would that destroy the physics bodies of the children?

There’s no special rules. If the GameObject the Rigidbody2D is on is inactive, there are no physics bodies. It doesn’t matter how that GameObject is inactive, be it child or not. The physics system doesn’t care about such rules. It doesn’t even understand the hierarchy.

I explain it like this at a high level because answering it as some “specific situation” level would suggest it’s a special circumstance, it isn’t.

1 Like

Thank you for your answers! and patience :smile:

1 Like