Monday, December 8, 2014

Why Don't Particle Systems Collide with Sprites?

If you ever try to use Unity's particle system in 2D, you'll find that it doesn't quite work the same way as in 3D.

Simple particle system, straight out of the box.
Sometimes Unity is a joy to use: it does all the hard work. For example, Particle System is an amazing feature. You want smoke? Particle system is your answer. Rain? Particle system. Squirting blood? Why not a particle system; that's what some people use.

However, sometimes Unity is a pain. Adding a seemingly straight forward feature takes days of research on the web.

All last week, I had been trying to get a particle system to collide with sprite objects in my 2D game without any success. No matter what I tried, the particles just passed straight through the sprite, as if it weren't there.

Particles Not Bouncing Off Sprite.
In addition, you will notice sometimes the particle stream would pass in front of my sprite, then mysteriously, it would start passing behind the sprite. Then a fraction of a second later, in front again!

One might think a quick search on the internet would give the solutions, but unlucky me, nothing obvious showed up when I tried. In another post, I describe the state of Unity information on the net, which---in quick summary---is "frequently out-of-date". (This post will eventually suffer the same fate!)

The Sorting Fudge
First, I tried to cure the problem of rendering order. It looks strange if particles that have been passing in front of an object suddenly start to pass behind it. To fix, I used the "Sorting Fudge" setting in the "Renderer" property of a particle system. The name itself inspires no confidence, and neither does the tooltip, which mentions that the fudge "most likely" would work. In fact, it seems to work fine if I enter some value like "-5".
Having spent some time to, ummm, sort this out, I then sheepishly realized: ordering of course does not fix the main problem of the stream not colliding with the sprite.

More time spent tinkering, and reading on the internet... I tried adding a collider to the sprite. Nope. Perhaps it also needs a rigid body? Don't bother! Perhaps a rigid body for the particle system as well? That was Desperation speaking.

Finally, I stumbled across a forum discussion that stated particle systems simply do not collide with 2D sprite objects. That was the key to solve this puzzle.

To get the scattering effect I added a 3D object that has an appropriate shape as a child of the sprite object. As I do not want to see the child, I also turn off the mesh renderer.

Success! Particles scatter against an invisible 3D cylinder.
Furthermore, I extended the 3D object far enough into, and out of, the 2D plane, so that the effect is not spoiled by particles that could fly further out in front of, or behind, the plane.
2D is really 3D
This last observation explains why particle systems do not collide with sprites. As you know, Unity in 2D is really a flat view of a 3D set up. Particle systems themselves inhabit a three dimensional world. The likelihood of a particle in the three dimensional system to hit a flat two dimensional object side way is thus quite low. We need a 3D object with a non-negligible cross section to collide with.

The "rendering order" mystery can be explained by this effect as well. Because the particles are randomly emitted inside a unit circle, about half of them would fly in front of the 2D plane, and half behind. The half in front are enough to give the impression that the stream passes in front of the sprite. However, it could happen every once in a while, and for a short time, that all of the particles go behind the plane. Thus temporarily, the particle stream appears to pass behind the sprite.

Hope this helped you. At least until Unity changes its behavior.

No comments:

Post a Comment