Calling the physics simulation from C#

@hangemhigh Both seem like they would. The first example is more simple, though. Just would need to add a way to rewind back to your current state after you grab the “future” position.
If you’re wanting to know the position of an object at 2, 3, and 5 seconds from the current time I’d suggest something like this.

//Store state of the object at the current time (start time),
//Simulate(2f) to simulate 2 seconds from the current time
//store the state of the object(2f). Current physics time is now at startTime + 2f
//Simulate(1f). Since the physics time is now at startTime+2f, this will put you at startTime+3f.
//store the state of the object(3f)
//Simulate(2f). Since the physics time is now at startTime+3f, this will put you at startTime+5f.
//store the state of the object(5f)
//Restore the state back to the start time. (via setting the pos/rot/vel/aVel back to whatever it was)

It’s important to note that every time you call Physics.Simulate EVERY body will be simulated at once. There are some posts in this thread on how to only step one rigidbody, not the entire simulation though. If you have multiple physics object, you need to store the state for them all at the start, and restore to that state when you’re done “looking into the future”.

1 Like

Ok. Thanks for the info.

It is interesting that it says this “Using step values greater than 0.03 is likely to produce inaccurate results.” on the Physics.Simulate page. I will give this a try by the end of this week and put some comments if I run into issues.

Yes. Simulate just runs a physics step with the timestep provided. If you expect that to be accurate, that must be the same tilmestep your game uses. If you need to simulate for longer than one tilmestep, you will need to loop.

Edit: I do wonder how on earth “timestep” became “tilmestep” twice in a row…!

2 Likes

Hello guys. Related to this post, I have just developed an object scatter that will allow you to automatically place object around with physics. It includes also other cool features (imho :smile: )

Apologize if this is considered a shameless spam, but I do think it is related and I actually got some info from this post for building it. For screenshot and video see here: [RELEASED]Physics Scatter: scatter objects in the editor, with physics - Community Showcases - Unity Discussions

Trying to understand if Physics.Simulate() can fix my problem – I’m trying to implement a friction on some ConfigurableJoints I have in a project. Basically, the joint has all the normal restrictions plus a “friction force” which subtracts a fixed magnitude of angular velocity (and the corresponding linear velocity based on the offset of centerOfMass to joint connection) in the opposite direction of current movement.

The problem lies in making sure this friction is subtracted from the final velocities AFTER all other forces are applied in the various FixedUpdates (joint connection forces, external “explosions” from other objects in the scene, etc.) as well as the automatic unity forces (gravity, collisions). There’s several limitations:

  1. There’s no PostDragAndCollisionsUpdate, or even a LateFixedUpdate for that matter (I guess you could do script ordering but I’m trying to avoid it).

  2. You cannot grab the net velocity added to a rigid body so even if I hack a LateFixedUpdate there’s no way to get what the final velocity will be (not to mention gravity, drag, and collisions have not yet been applied).

Looking at this thread and testing on my own I discovered the order of operations to be

  • Call FixedUpdate() for all objects.
  • Apply the net velocity from all received AddForce/AddTorque calls
  • Apply drag and angular drag
  • Apply collision forces

So my question is, how many of these steps are still hidden inside Physics.Simulate()? It sounds like FixedUpdate calls are still outside (and I imagine collisions are stuck inside) but what about drag and angularDrag? If I adjust the execution order for a CustomSimulationScript to be last can I create a pool of my joint objects and grab their final velocities somehow, apply my own drag formula (the friction), and then call Physics.Simulate()?

If not, would it be that difficult to expose the necessary information on Rigidbodies? Right now I’m simply acting on the final velocities from last frame and reverse engineering the required angularDrag and drag. It works okay-ish until there’s a significant change in velocity and weirdness ensues.

My conclusion at this point is that it’s impossible to get this working clean. Please show me how I’m wrong (:

Unfortunately, all of this is still hidden inside Physics.Simulate().

But since your custom drag happens on the final velocity after all forces/collisions are applied, you should be fine with just making yourself a LateFixedUpdate() after calling Physics.Simulate(), and handling it in that. Although… the effect of the drag will always be one frame late. It may end up being unnoticeable.

I understand that what you’d really need is a point where the final resulting velocity for this update has been calculated, but not yet applied as movement (right?). I actually remember a situation where I really would’ve wanted that for making custom character controllers. I ended finding a solution indirectly through ComputePenetration, which allowed me to solve my own collisions whenever I wanted and therefore make my own physics, sort-of. But this solution may not really apply to your situation since you’re using joints

1 Like

Oh… my… god… you’re totally right. The instability in my current implementation only gets out of hand because I’m hacking the drag which is taking a percentage of the wrong frames velocity, while your solution takes the exact needed velocity change and simply applies it later (so the error doesn’t scale over time).

In fact, does Physics.Simulate() actually setup the interpolation or does it merely adjust the velocities (and position in the case of collisions)?

Couldn’t I just update the rb.velocity and rb.angularVelocity on my pool of joints after calling Physics.Simulate()?

Simulate() calculates the final velocities and applies the actual movement, but I’m not sure about interpolation. We’d have to test that.

yup. I think that’d work

So I figured out the order of things:

  • Physics.Simulate() updates the cached end point for the actual physical movement whenever you choose to call it.
  • Rigidbody uses currently cached physical end point and calculates the selected interpolation for given Time.deltaTime (after FixedUpdate but before Update)
  • Update() methods are called after that frames interpolation value has been applied to the transforms.

I setup a manager that registered Rigidbody’s and set their velocity and angular velocity to zero each Update/FixedUpdate after calling Physics.Simulate(). Below are the two separate setups I chose (commenting the other out when testing)

  //Scheduled to trigger BEFORE all other Updates()
   void Update ()
    {
        if (Physics.autoSimulation)
            return;

        mTimer += Time.deltaTime;
        if (mTimer >= Time.fixedDeltaTime)
        {
            mTimer -= Time.fixedDeltaTime;
            Physics.Simulate(Time.fixedDeltaTime);

            if (mLateFixedUpdateGameObjects != null) {
                for (int i = 0; i < mLateFixedUpdateGameObjects.Count; i++) {
                    Rigidbody[] rbArr = mLateFixedUpdateGameObjects [i].GetComponentsInChildren<Rigidbody>(false);
                    for (int j = 0; j < rbArr.Length; j++) {
                        rbArr [j].velocity = Vector3.zero;
                        rbArr [j].angularVelocity = Vector3.zero;
                    }
                }
            }
        }
    }

   //Scheduled to trigger AFTER all other FixedUpdates()
   void FixedUpdate ()
    {
        if (Physics.autoSimulation)
            return;

        Physics.Simulate(Time.fixedDeltaTime);

        if (mLateFixedUpdateGameObjects != null) {
   
            for (int i = 0; i < mLateFixedUpdateGameObjects.Count; i++) {
                Rigidbody[] rbArr = mLateFixedUpdateGameObjects [i].GetComponentsInChildren<Rigidbody>(false);
                for (int j = 0; j < rbArr.Length; j++) {
                    rbArr [j].velocity = Vector3.zero;
                    rbArr [j].angularVelocity = Vector3.zero;
                }
            }
        }
    }

I then put a script on a chain of ConfigurableJoint’s that constantly applied smooth varying force and torque.

Update() - Failed to cancel all the velocity. It slowed the velocity to a small speed (it was letting one frame of force through). Additionally, the movement was jittery and the physics behaved differently.

FixedUpdate() - Also let one frame of force through but was not jittery.

This is why I think the smoothing is done between FixedUpdate and Update but it uses cached values from when Simulate was called. Luckily, you can just detect when the friction brings it to zero and call Sleep() on the Rigidbody after a certain number of frames (and maybe raise the drags on registered rigid bodies to slow them as they count to sleep).

FWIW, there actually sort of is a LateFixedUpdate built into the engine, it was just misdocumented for years.
yield return new WaitForFixedUpdate() returns after the physics step and all collision callbacks but before the next FixedUpdate or Update. They have updated the docs to reflect that.

1 Like

That is a nicer point for my solution because even putting it as the last FixedUpdate doesn’t come after the OnTriggerXXX OncollisionXXX callbacks but WaitForFixedUpdate() does. Thanks!

I was just coming looking for something like this and wow its already in the version i have :slight_smile: Awesome. I needed it because I need deterministic physics for non random gameplay so that you can have replays where you pause and slow down the game without effecting the fixed timestep size because things calculate in between time steps. Example is this enemy close enough to auto attack it.

@yant
Is it possible to get the position in just one frame. I want to know the position of rigidbody after 3 secs but Physics.Simulate have only timeStep as parameter. I will have to loop it with update or coroutine.

When I try to use for-loop in one frame it freezes the main thread. And we cannot even use other thread for calling Simulate method.

Is there any other way I can get the position in advance without freezing Unity Main thread ?

I am Having same issue , have you done it @hangemhigh ?

I think you really do need to call Simulate() several times in a loop with the regular physics timestep as parameter. Otherwise you’ll get different results than what really would’ve happened (as I try to picture below )

For the main thread blocking problem, I don’t think there is much we can do except:

  • Wait for the ability to simulate only individual rigidbodies or rigidbody groups (so it’ll cost way less for the main thread)
  • Wait for jobified 3D physics (2D physics jobification already in progress: video )
  • See if your situation is eligible for making custom physics that you can simulate yourself. For instance, if this is for planning the trajectory of a golf ball, it would probably be a good idea to make your own deterministic simulation for the golf ball (using sphereCasts, overlapSpheres, computePenetration, etc…).

Yes, you’re right. You have to advance the 3 seconds of time in fixed-update steps otherwise the result might not be accurate enough.

So is this ever coming to Unity or nah?

4 Likes

Hi there!
Is it possible to make Simulate in thread?

You have to trigger Physics.Simulate from within the main thread context but it’s going to off-load as much work as possible to the other threads internally. It’s not single-threaded at all.

1 Like

Is partial scene simulation still planned? Is it not possible due to PhysX?

1 Like