Particles and queues and alpha blending, oh my

I have a transparent floor in part of my game, with some particles spilling upwards to mark a spawn point.

What happens is this. If you are close to the particle emitter, you see this:

But if you back up a little you see this:

Now, I was able to find some suggestions to the extent that if I removed the queue tags from some of these shaders that might help. I made a copy of the built-in transparent diffuse shader (in use by the floor panels) and I turned off the queue-- that solves the problem of the particles appearing behind the tiles all the time. But now they never appear behind the floor at all- they are always at full brightness.

I tried setting the renderer to Sorted Billboard but that doesn’t seem to have an effect.

Is there some configuration I can do to get a particle effect whose particles render in a “normal” way? I’d like the particles to render behind the floor/wall tiles when they are behind them…

This seems to be the classic case of “getting transparent objects right is hard”.

Basically, the solutions are several:

  1. Avoid semi-transparency when you can. Maybe the floor only needs 1-bit transparency (e.g. Transparent/Cutout shaders)? Maybe the shader can draw it in two passes, so that fully opaque parts are right, and semi-transparent parts will only sometimes be wrong?

  2. If you know, for example, that particles are always “in front” of the floor, then you can set that in the shader. For example, setting render queue to “Transparent+1” in the particles shader will make them always render after everything that is in Transparent queue.

  3. Transparent objects are sorted back to front on a per-object basis. If you split up the floor into several objects, then sorting will probably be better. Of course, you’ll end up with more objects which is worse for performance.

So it’s been a while, but I handled this by having these effects do the following (pseudocode)

function Update()
{
   if(Vector3.Distance(effect.transform.position,maincamera.transform.position)<Vector3.Distance(node.transform.position,maincamer.transform.position)
   {
     effect.renderer.material.renderQueue=3001;
   }
   else
   {
     effect.renderer.material.renderQueue=3000;
   }
}

… where “node” is the object that owns the square the effect is sitting on (but which gets hidden by the CombineChildren call during system startup).

I only have a few of these particle effects going on at a time, so there’s very little overhead, and it seems to have resolved the issue.

Are there any downsides to swapping renderqueues in runtime?