I am starting a new thread about physics determinism (especially when using PhysX and 3D) to discuss and summarize the current state of it. There are lots of old threads about it, the best I found being this where @RedGirafeGames and @MelvMay solve an issue: Can't get same result from auto and manual simulation of Physics Scene
Personally, I do have lots of experience on the topic from various platforms and I am painfully aware of how hard it is to achieve determinism, especially if using floats. If any operations are performed in different order or math library is updated - or for a thousand other reasons - the determinism may be lost.
My game (currently in beta, Turbo Sliders Unlimited on Steam) online MP is based on clients predicting the future based on updates coming from host and known controls already made. This generally works smoothly (with fixed time steps and enhanced determinism set on), at least when prediction times are less than 200 ms, implying that things are quite deterministic. Now that I also implemented game recording and playback, I would like to optimize the amount of full state updates needed. I noticed that warping caused by non-determinism becomes visible with intervals as low as 500 ms, especially after collisions. If I start my game, record a game, exit, and then restart game and play back the recording, it works correctly. But if I then restart the recording without exiting the game, determinism is lost, especially after each collisions. But it seems that it is always lost the same way. If I keep restarting the playback, the warping seems to always look the same.
I understood from previous discussions that this is most likely because the colliders are in different order somewhere inside PhysX, because the exact order of initializing stuff has not been the same. In my case, it means first creating scene, then creating vehicles, then moving them, then destroying them and recreating them in the original positions. I noticed that if I query all the colliders in the scene at this point with physicsScene.OverlapSphere, I get the same colliders but in different order, which probably explains the non-determinism. I am not sure though if this is the only problem there is, though.
So, right now I am wondering whether there are any low-hanging fruits to improve the determinism as much as is possible, still understanding that full determinism is probably never possible. So, some questions to anyone who feels like answering:
-
PhysX is said to be deterministic on one platform if the same operations are performed in the same order (and enhanced determinism is on). But what kind of operations can break this? Can just moving an object around (from A to B and back to A instead of just not moving at all) cause it to break or is it more about the order of initialization? This question is relevant in online MP where clients frequently move objects around based on server updates and prediction ticks. If just simple movement via a different point can break determinism, there is not much hope to achieve full determinism.
-
Is there some way to reset the physics state to a deterministic state that is fully derived from the current physics objects in the scene? Could it work if I just disable all physics objects so that there is nothing there, and then reactivate all objects in a deterministic order? Or is there some hidden state inside PhysX that so that even that might not work? It would be so nice to have some kind of Reset function that would make PhysX’s internal state be deterministic based on the objects it currently has but I guess that is too much to ask?
-
My scene currently has hundreds of colliders, most of which are terrain colliders. Do you see that using a separate PhysicsScene could somehow help solve the issues here? The API to do that seems just very limited so I don’t know how that could be done. It also seems that some external plugins I am using (at least EasyRoads3D) assume that the default physics scene works and I didn’t notice there being any way to create a new physics scene and making that the default. What I could try is create a new scene after the first initialization has been done. It is quite a big change to make so before trying to do it, I would like to get an opinion whether it would in theory help. To clarify, that would mean creating a separate empty physics scene, then movíng every object (including terrain and roads) with a collider there in a deterministic order whenever a new game/playback is started. Restarting game/playback would then mean moving objects back to main scene, destroying the temporary scene, and then creating a new physics scene, and moving objects there again. This seems like lots of hassle (and possibly break something else) and I am not sure if it is worth the effort but is the best idea that could be tried?