Physics.Simulate for a single object - possible ?

Hello,

is there a possible way of applying Physics.Simulate for a single object only ? and leaving all other physics bodies un-simulated ?

also will enabling kinematic for a certain object be the same as not simulating physics for it ?

Thanks.

2 Likes

Yes, you may run that object in a separate physics scene:

Really appreciate your response, this is an incredible idea, but will it have a performance impact if I did it for 100+ separate rigid bodies ?

The problem I am currently facing in multiple scenes is that I still want different game objects in separate scenes to still interact with each other and the main scene which includes, lets say, the terrain while still maintaining the separate physics simulation.

Test it. It does not take more than 10 mins to write such a test, and will be quite insightful.

Indeed I tested it out, I instantiated 100 primitive cubes with a rigidbody attached to it, each one in its separate physics scene, and simulated all 100 cubes at the same time every 0.02 ms, it heavily impacted performance spiking CPU for 4 ms to 120 ms and dropping my frames from 200 to 6-7 frames per second.

I had missed this one. Physics will be simulated in the way that other objects will be able to collide with the kinematic rigidbody. The difference is that this body won’t react to any physics interactions.

Which is in someway what I want it to do, I was wondering if it will be as deterministic as calling Physics.Simulate which plays a big role in my project.

This doesn’t seem right, that it would cost so much for just 100 separate simulations. Even considering physics setup cost, it’s just one rigidbody per scene.

I’ll test it again and check if I am updating the scenes correctly.

Here’s how I am testing it out, it seems like going above 70’ish really affects performance, assuming I am doing it right :

//Don't forget to include UnityEngine.SceneManagement;

    static int scenecount = 0;
 
    delegate void myDelegate(float step);
    static private myDelegate updatePhysics;
 
    List<PhysicsScene> pScenes = new List<PhysicsScene>();

    void Start()
    {
        for (int i = 0; i < 100; i++) //number of objects to spawn
        {
            CreateSceneParameters csp = new CreateSceneParameters(LocalPhysicsMode.Physics3D);
     
            scenecount++;
     
            Scene scene = SceneManager.CreateScene("Space" + scenecount, csp);
     
            GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
     
            cube.transform.position = new Vector3(0, scenecount, 0);
     
            cube.AddComponent<Rigidbody>();
     
            pScenes.Add(scene.GetPhysicsScene());
     
            SceneManager.MoveGameObjectToScene(cube, scene);

            updatePhysics += scene.GetPhysicsScene().Simulate; //add it to the delegate
        }
     
    }

    private void FixedUpdate()
    {
        updatePhysics(Time.fixedDeltaTime);
    }

Interesting use of delegates. I agree that shouldn’t be so performance intensive, so I gave it a test myself.

using UnityEngine;
using UnityEngine.SceneManagement;

public class PhysicsTest2 : MonoBehaviour {

    PhysicsScene[] scenePhysics;
    float timer = 0;
  
    void Start() {
        QualitySettings.vSyncCount = 0;
        Physics.autoSimulation = false;
        Physics.gravity = new Vector3(0, -1f, 0);

        GameObject floor = GameObject.CreatePrimitive(PrimitiveType.Cube);
        floor.transform.localScale = new Vector3(100, 1, 100);
        floor.transform.position = new Vector3(0, -0.5f, 1);

        scenePhysics = new PhysicsScene[100];
        CreateSceneParameters csp = new CreateSceneParameters(LocalPhysicsMode.Physics3D);

        for (int x = 0; x < 10; x++) {
            for (int z = 0; z < 10; z++) {
                GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
                cube.transform.position = new Vector3(x * 2f, 1, z * 2f);
                cube.AddComponent<Rigidbody>();

                int index = (x * 10) + z;
                Scene scene = SceneManager.CreateScene("MyScene" + index.ToString(), csp);
                scenePhysics[index] = scene.GetPhysicsScene();

                SceneManager.MoveGameObjectToScene(cube, scene);
            }
        }
    }

    void Update() {
        timer += Time.deltaTime;
        while (timer >= Time.fixedDeltaTime) {
            timer -= Time.fixedDeltaTime;
            foreach (PhysicsScene scene in scenePhysics) {
                if (scene != null && scene.IsValid()) {
                    scene.Simulate(Time.fixedDeltaTime);
                }
            }
        }
    }

}

I’m getting 120fps for the simulation.

As for cross scene interactions, no way. That defeats the purpose/idea behind separate scenes. If each scene had to check physics against all other scenes they wouldn’t be separate. You could almost certainly fake things if you really needed to by passing data around, ghost copying colliders here and there, but it would be messy.

I think you will have better luck working with layers. You can set layers to not interact with certain other layers using LayerMasks, and Physics.IgnoreCollisions and things, to make your objects not touch each other, but still touch the terrain. For example my player spells do not interact with the player or with each other, but will hit buildings, monster, and the environment, etc.

3 Likes

thanks for checking out my thread, I agree with you about scene interaction and the Idea of separate scenes, but I just need a way to call Physics.Simulate for a single Rigid Body in the same scene, I’ve been testing some things by switching on/off isKinematic before calling physics.simulate and preserving velocity and angularVelocity for rigid bodies but it will not give the same result in repeated simulation data which is important for my projects.

What are you trying to do exactly?
I feel like you’re approaching this problem in a very weird way.
Like @malkere said, if you don’t want stuff interacting with each other you can just modify the collision matrix in the physics settings.

a similar approach to networking physics using deterministic lockstep, at some moments I need to simulate objects while other objects needs to be un-simulated while preserving their previous forces.

regarding objects interacting with each other, I do need them to interact with each one another and collide even if its frozen/un-simulated

1 Like

Physx itself is not deterministic, it will diverge over time due to numerical inaccuracy. It’s small, but it is there. If it’s just simulate some but pause others, you don’t need or want separate simulations. Use layers or ignore collision commands.

I can handle small inaccuracies by fixing the client slightly without him noticing and I achieved that, but for now I need to choose a subset of rigidbodies to simulate while keeping others un-simulated until enough input buffer is available then advancing these ones to catch up in the simulation with the other rigidbodies, currently if one client had some packets lost or a connection problem and the available buffer for that client is now empty the whole server will have to wait for that client to feed us with his inputs for the lost frames and then continue the simulation, this is clearly unacceptable and will lead to fix each client, I can get around this by creating one separate scene for local physics and move rigidbodies with not enough buffer there to not include them in the simulation but when the input is received I will not be able to simulate multiple frames at the same moment without affecting other normal running connections and will lead to fix that client and moving him a huge step backwards.

if @yant could check this out

Just interested if it’s possible to parallelize physics simulation on multiple threads via async/await mechanism.
Seems like a local PhysicsScene is what I was looking for.
I could put my gameobject groups intro separate PhysicsScenes and run simulation of each one in a separate Task. Those gameobjects can’t interact to objects from other groups though, between itselves only.
Will it work?

That sounds incorrect. PhysX itself is deterministic and has flags like PxSceneFlag::eENABLE_ENHANCED_DETERMINISM to deal with edge cases that break it. See the manual.