Shuriken – World Particle Collision
With Unity 4.0 we are adding support for world particle collsion detection. It’s quite awesome and very fast.
We spent a lot of time optimizing world particle collisions and also did more than a few optimizations to Shuriken in general. Especially on mobile devices Shuriken got a very big performance boost.
Shuriken is multithreaded and so is collision detection.
The reason why particle world collision becomes slow is due to the sheer number of raycasts and complexity of the raycasts performed. We have done several optimizations to minimize this cost.
We added support for batching raycasts. So we first find all PhysX shapes that touch all particles in a particle system, perform very fast cache localized early out culling of raycasts against those shapes on a per particle basis. Only then do we perform any per collider raycasts. This dramatically increases performance because at any one time, very few particles actually need the full collision check.
One side-effect of this approach is that creating small colliders that are axis aligned will give you a performance boost. For example if you have a corridor. It’s a good idea to separate the walls and the floor into separate colliders.This way when particles are simply flying through the corridor without colliding, Shuriken can quickly skip expensive computations. In almost all particle effects, most particles are not colliding during any single frame. Thus it always makes sense to create colliders with slim bounding volumes.
Yet when you create scenes with massive amounts of particles, for example performing 50,000 raycasts every frame, it can quickly become a bottleneck. Thus we added support for an approximate collision detection mode. It allows you to define an upper limit on the amount of raycasts performed each frame. This gives you complete control over the maximum time spent on raycast collision. Naturally this comes at the cost of particle collision accuracy. In some cases, particles might fall through surfaces or collide with non-existing geometry. In many cases, some particles falling through is invisible to the user since they will just disappear. Especially with a high particle density this becomes unnoticeable. A framerate drop due to lots of particle collision detection on the other hand can be very noticeable.
In order to reduce quality degradation we store previous collisions in a cache, essentially in a voxel grid defined by space and velocity. Each grid has a single plane in the cache which is then reused for all particles that travel through this voxel. If the number of particles exceeds the budget, some particles will perform only cheap voxel lookups and reuse information in the cache. An almost free raycast.
In the particle system you can choose High Quality (always performs full raycasts), Medium Quality (gets a portion of the raycast budget every frame) and Low quality (gets a portion of the budget every couple of frames). Generally speaking any effects that are chaotic in nature work extremely well with low and medium quality mode. Such as smoke, sparks, dust, and precipitation. Low and medium quality only casts against static geometry. And the cache will usually converge fairly quickly, at which point very few raycasts need to be performed while giving very good looking results.