Physics Changes in Unity 2018.3 Beta
The main change Unity 2018.3 brings to physics is the 3D physics engine upgrade, from PhysX 3.3.3 to PhysX 3.4.2. It’s the first time we ship the latest available version of PhysX to date. We aim to improve performance and stability and make it extremely easy for you to upgrade your project. Read this post to learn more about the upgrade and all the specific changes and new features related to working with physics in 2018.3.
PhysX 3.4 represents several years of progress in the area of computational physics. We used to wait for a year or so to let the new version of PhysX mature, before shipping it in Unity. This time around we’re shipping the latest one, after having put as much effort into testing as possible.
We’re also going light on new features this time around, to pay more attention to the core stuff that was already working. We aim at as fewer regressions as possible. Join the Unity 2018.3 beta and try it for yourself!
PhysX 3.4 upgrade
PhysX 3.4 is a big release that brings visible improvement in a whole bunch of various ways. Firstly, it addresses a significant amount of bugs. For instance, it significantly improves convex-convex collision detection and feedback, so that there are no more any odd bumps from the ground when the PCM collision detection is enabled. Physics queries against thin and long tri angles have been improved. Another example is the improved precision of contacts computation with Terrain. Secondly, the physics engine now saturates the threads with physics jobs much better. Broadphase, collision detection and the solver were re-written to be decomposed into as many atomic jobs as possible. As a result, you should see the time it took to simulate a frame to be lower than before.
Thirdly, the physics queries module is now up to two times faster than before.
There are a lot of great new things added to PhysX 3.4, read on to learn more about the features that we support in Unity 2018.3.
We used to have only one physics scene that we populated with all the bodies and colliders from all your Unity scenes. Certainly, there are particular cases where this is limiting, so we have now enabled you to create multiple physics scenes. With that change, you can now specify whether a given Unity scene uses the default physics scene, or needs its own local one. The extra scenes are just like the default one, with the exception that all the usual Physics.* APIs will ignore them, because all the scenes are created completely independent. There is a number of ways to use the extra scenes. You can simulate them with PhysicsScene.Simulate on any frequency (think multiple parts of your world simulated with different frequencies). Another interesting option is to create an invisible physics scene to predict trajectories. This improvement is available to both 3D and 2D physics.
More batched queries
Batched physics queries is a way to run physics queries off the main thread. This API is needed because one can’t execute the usual API from another thread. In Unity 2018.1, we shipped RaycastCommand.ScheduleBatch that helps to compute raycasts off the main thread. In Unity 2018.3, we’re extending this to add the other single-result queries like SphereCast, CapsuleCast and BoxCast. We’re figuring out the technical limitations that prevent us from exposing the multiple-result queries like overlaps and sweeps for future releases.
PhysX guarantees the same simulation result when all the inputs are exactly the same. However, many things are considered “input” from the perspective of the physics engine. One such thing is the physics scene itself. Before 2018.3, it wasn’t possible to destroy the implicit physics scene. One could only destroy all the objects in it, which formally wasn’t enough. With multi-scene physics, this is easy to work around. However, another frequent issue was that adding a new body located somewhere far away and seemingly not interacting with the other objects also had the potential to change the simulation outcome. That was because of the way PhysX in Unity grouped objects internally. This is now possible to overcome by enabling a special option in the physics settings. It’s not free in terms of performance, but it shouldn’t slow your project down significantly.
TerrainCollider used a special collision detection algorithm that revolved around some inaccurate assumptions when computing contacts as well as a few unobvious features alike terrain thickness. In Unity 2018.3, the collision detection approach used is the same as when computing contacts with meshes.
Speculative continuous collision detection
Continuous collision detection has been an option in Unity for a while. However, the linear nature of the process was a common problem. All it did internally was to sweep the bodies some specific distance forward along the velocity vector to compute the time until next hit. This model didn’t allow for rotations support.
The simplest example of a game where that’s problematic is Pinball, where the flippers rotate fast while not being linearly moving at all. This is no longer a problem with the alternative continuous collision detection algorithm added in the 2018.3 release. It works by inflating the contact offsets that affect the generation of contact points. It generates the actual contact manifold once the objects are close enough according to that inflated distance. The predictive linear sweeps are no longer used in that mode, so it tends to be more accurate by detecting overlaps with all sorts of bodies being rotated or moved in a fast manner.
We’re introducing new friction modes: single-directional friction and two-directional friction. The default friction model works by creating up to four scalar constraints per contact pair. This is the fastest model to compute, and it also converges fast, not requiring too many solver iterations. Both of the single-directional and two-directional friction modes work on a per contact point basis, not per contact pair. It’s potentially more accurate, but also requires more solver iterations to converge and, in case your project generates many contact points per contact pair, it can slow your project down.
No automatic transform syncing in new projects
By default, all the changes to Unity transforms were synced to the physics engine right before they might be needed. That is, every time a raycast is run, every time a simulation is run and so on. Syncing isn’t the fastest operation, and it makes sense to reduce the number of times it’s called. For that reason, we have a setting that turns off all the automatic sync points. You’re responsible for calling Physics.SyncTransforms, as otherwise transforms are synced only right before the simulation (=FixedUpdate).
Another problem with the sync points is that syncing itself can only happen on the main thread. That means, for instance, that you can’t have a raycast that includes syncing. Generally, as Unity becomes a more multi-threaded engine, it’s increasingly more often that new projects need to have the automatic sync points off. That said, we’re changing the default value of Physics.autoSyncTransforms from true to false for all new projects starting this release. This improvement is available to both 3D and 2D physics.
Obtaining contacts without garbage
Getting contacts information has always caused some unavoidable managed heap allocations. The allocations were made to pass in the instances of the Collision structure to the handlers in scripts (=OnContactStay for instance), as well as the arrays of contact points. Depending on the frequency of the events, it could hurt performance of certain projects.
In 2018.3, we introduce a new property Physics.reuseCollisionCallbacks, which is off by default to keep the behavior consistent when you’re upgrading your existing projects. However, if you turn it on, the Collision instances are going to be shared. Effectively, it means that there is only one instance of the Collision class that is reused every time the callbacks are fired. As a consequence of that, there will no longer be any garbage produced. However, the collision information you receive in the callbacks has to be copied manually if needed. This improvement is available to both 3D and 2D physics.
Drive for quality
We have a goal of making this release very easy to upgrade to. To achieve that, we dedicated a lot more hours of testing and reviewing than ever before. First, we’ve sent out builds to early adopters. Then, we’ve made a limited functionality upgrade work in Unity 2018.2 and made it available for testing as a spin-off build during 2018.2 alpha. Afterward, once 2018.2 went public, we’ve started a forum thread and invited enthusiasts to provide feedback. This resulted in a pretty productive discussion with a few bugs fixed, and some features added too. Once 2018.3 beta became a thing, we’ve merged our upgrade branch there, and right now it’s used in more than 10000 editor sessions a week. We’re still looking for feedback though, so join the beta and talk to us on the Physics forum or the 2018.3 beta forum!