Shuriken ParticleSystem Observation #2: The perils of Sort Mode

When I started experimenting with Unity’s new Shuriken particle-system, I never thought I would have much to say about the Sort Mode control in the Renderer module. As any experienced particle-system designer knows, some particle-systems will look much better if the particles are rendered in a particular order, and Shuriken offers four choices: None, By Distance, Youngest First, and Oldest First. Pretty obvious choices, or so I thought. But as I studied the results of these choices more closely, I quickly realized that my intuition about expected behavior was running counter to the actual behavior of these settings. There is actually a lot of need-to-know details about how Shuriken implements these particle render-ordering options that are not covered anywhere in the Shuriken ParticleSystem documentation, and so far, do not appear to be answered at Unity Forums or UnityAnswers. I will attempt to fill in some of this information here.

First of all, the rendering order of particles within a particle-system is not really an issue unless your particle-system produces overlapping particles and they are rendered with a shader that uses an order-dependent blend. Obviously, if the particles are scattered in all directions, rarely overlapping, the order they are rendered is not going to matter. The same holds if you are using a shader like “Particles/Additive” with a blend that adds color directly to the frame-buffer, an operation which is mathematically commutative, (a+b = b+a). In these cases, you just want the fastest option, (most likely Sort Mode = None).

However, if you are using an order-dependent shader like “Particles/Alpha Blended”, a more suitable shader for something like smoke, then you have to start thinking about particle render-order and what Sort Mode option is most appropriate.

Let’s continue with a smoke effect as an example. For a cloud of relatively dense smoke particles, perhaps from a small explosion, the render-order of the smoke particles is still probably not an issue, however, if the smoke lingers for a while, you should still be concerned about whether the (possibly arbitrary) render-order of the particles remains consistent from frame to frame. If the render-order is not frame-to-frame coherent, you will likely see obvious “popping” glitches as particles suddenly appear in front of others that were previously covering it.

A Shuriken Sort Mode of None, is obviously not sorted, but it’s also (less obviously) not frame-to-frame coherent, at least, it loses frame-to-frame coherence when the particles have mixed-length lifetimes. When a particle in the middle of the particle-system’s array of active particles expires, it gets removed. To fill the array gap it leaves behind, Shuriken appears to use an algorithm which copies a particle from the end of the array into the gap. This is a fast algorithm, but it also breaks any frame-to-frame coherence. The visual “pop” you get when a particle suddenly jumps to a new location in the render-order can be real obvious, so if this problem arises, you’ll need to consider using one of the sorted options.

The additional options for Sort Mode are By Distance, Youngest First, and Oldest First. Based on my experiments, By Distance works great and does what you’d expect: particles closest to the camera are drawn last so that they appear in front of those that are farther away. The problem with By Distance is that it is most likely, by far, the most expensive choice. For each frame, a distance must be calculated for each particle and then the whole array sorted accordingly. Of course, it’s there if you need it, but if a cheaper sort works, you should probably use that instead.

So that leaves Youngest First, and Oldest First. Obviously, for Youngest First, older particles are rendered on top of younger ones and will appear closer. For Oldest First, the opposite ordering is used. But wait, what exactly do the words “Youngest” and “Oldest” mean? My first guess would be that they refer to the literal age of the particles. The oldest particles would be the ones that have been active the longest, those spawned the longest time ago. The youngest particles would be those most recently spawned. As it turns out, if your particles do not all have identical lifetimes, this is not how Shuriken interprets “Youngest” and “Oldest”. Where I prefer an “absolute-age” interpretation, Shuriken uses a “relative-age” interpretation. In other words, the particle “age” value used for the Youngest First, and Oldest First sort modes is calculated as a percentage progress through a particle’s lifetime. A particle with a 6 second lifetime that has been active for 4 seconds will be considered older than a particle with a 10 second lifetime that has been active for 5 seconds.

This is how the calculations look using the values stored in the ParticleSystem.Particle structure. (Note that startLifetime is the full-lifetime of a particle and lifetime is the remaining lifetime. They used to be named startEnergy and energy, respectively.):

absolute-age = Particle.startLifetime – Particle.lifetime
relative-age = (Particle.startLifetime – Particle.lifetime)/Particle.startLifetime

I personally find Shuriken’s relative-age sorting to be strange, and less useful, but I suppose it may have its uses. I would typically choose absolute-age Oldest First sorting for a smoke plume that will usually be observed from about the same level as the smoke emitter (looking up). A relative-age Oldest First sort might be preferred if the particle movement is linked to the lifetime somehow. Perhaps if a particle’s relative-age determined its position along a path or spline or something, but I haven’t run into these kinds of particle-systems very often.

Try out the Unity demo embedded in this post to get a feel for how the appearance of a smoke plume is affected by the chosen Sort Mode. The lifetime for these particles has a fairly wide range of 2-30. You should observe that a By Distance sort looks nice and consistent. With a setting of None, you should observe occasional popping glitches. The Oldest First sort is probably acceptable here, however, if an absolute-age sort was used, it would look more like the By Distance sort.

Shuriken ParticleSystem Observation #1: Randomized parameters are not independent.

I love to use randomness in special effects design. Used correctly and cleverly, it can achieve highly varied and naturalistic results while keeping your effects from looking stale and repetitive. So I think it’s quite excellent that Unity’s new Shuriken Particle System allows you to specify random variation for many of its vast set of control parameters.

Typically these random variations are set using a “Random Between Two Constants” convention where you specify two values and an interpolated value is calculated at a random ratio between them. You can even specify random variation for dynamic parameters that change in relation to another value, such as time or speed. In this case, the “Random Between Two Curves” approach is used. Here you describe how the two values change using two curves. Over the life of a particle, different values are calculated using a consistent ratio between the curves which was randomly chosen when the particle spawned.

Now this is all terrific. With so many ways to specify randomly varying parameters, it looks like randomness plays a central and powerful role in the Shuriken Particle System. However, there is a dark-side to how the Shuriken Particle System implements its randomness. In contains an important, severe, and to some degree, flawed limitation that, as far as I know, is not described clearly in any of the particle-system documentation and can only really be inferred through experimentation and close examination of the particle-system scripting interface. In short, many of the randomized parameters used in the Shuriken Particle System are not independent of each other, they are linked, correlated. When you specify randomness for several particle parameters, the system does not make several random choices per-particle, but rather makes a single random choice and applies this same choice to each of the random parameters. (This is not strictly true for the “Force Over Lifetime” module which includes an option for having the random calculation performed every frame.)

Let me explain using a simple example. Using just a basic particle-system with no added modules, I can specify random ranges for particle Start Lifetime, Start Size, and Start Color. Using “Random Between Two Constants”, I set Start Lifetime to be between 1 and 6 seconds, and Start Size between 0.1 and 2. Using “Random Between Two Colors”, I set Start Color to be between red and blue, which will get shades of purple in between. Here is a picture of what this looks like using a wide bar shaped emitter along the bottom that keeps the particles in a vertical plane, (so that observed size differences are due to changes in particle size rather than perspective).

Look closely at the picture. Notice how all of the largest particles are red and the smallest ones are blue. This is because the random color and random size is correlated. One random number between 0.0 and 1.0 is picked and used to interpolate a color between red and blue AND a size between 0.1 and 2. Also notice that the large red particles never make it to the top. Only the blue ones do. This is because the lifetime randomness is also tied to the color and size randomness in a 3-way correlation. The large red particles live short lives while the small blue ones live longer. I don’t think this is a contrived example, (except that I’ve chosen wide and contrasting variations to make the correlation obvious). I often design particle-systems which randomly vary these particular parameters: size, color, and lifetime.

Now there may be some justification for correlating the random calculations on grounds of performance and efficiency. After all, we’re looking at multiple dynamic per-particle random parameters here. It may be too much to expect uncorrelated randomness here. All particle-system developers strive to find a balance between the amount of control that is available to effect designers and the amount of per-particle state information that must be tracked. Particle counts can balloon quickly and the memory used to track individual particles must expand accordingly. Every byte that goes into representing per-particle state must be carefully considered.

If you study the Particle struct used in the Shuriken Particle System scripting interface, you’ll find that it’s pretty compact, using only about 52 bytes-per-particle. The purpose of most of the struct’s values are pretty obvious: position, size, color, etc. A less obvious one is a float named randomValue. The documentation says it’s “The random value of the particle. This value is used to interpolate between the two curves when random between curves is used.” I don’t work for Unity and I’m not privy to how the particle-system is implemented, but it’s pretty easy to infer how this value is used. When a particle spawns, a random number between 0.0 and 1.0 is chosen and assigned to its randomValue parameter. Then throughout a particle’s lifetime, whenever the simulation needs a randomized parameter value, it uses randomValue to interpolate a value between its two specified constants or between two curves. This explains the correlated result shown in the picture above when color, size, and lifetime were all randomized. (I don’t know why Start Lifetime is correlated with the other two since Start Lifetime is stored explicitly in each particle’s state data. Its random value could be calculated independently and assigned directly to the state.)

So it would appear that the Shuriken Particle System correlates its random parameter calculations to keep the Particle structure compact, avoiding a much larger structure that would be needed to store many uncorrelated random values. However, if this is the main reason for the correlation, there is an alternative strategy that allows for an arbitrary number of uncorrelated random values without increasing the size of the Particle structure. Here’s how it might work. The current randomValue float would be replaced with an integer random-seed. When a particle spawns, a random seed is chosen and saved in the state structure. Then whenever the simulation calculates a particle’s random values, it first seeds a random-number-generator with the saved seed and than chooses as many random 0.0-1.0 values it needs. This technique does require some additional random number calculations, but you get independent randomness in exchange. It’s not a bad trade-off.

Overall, Unity’s new Shuriken Particle System is pretty good, especially the modular particle editor. But if you’re like me, and tend to incorporate a lot of random variations in your particle-system designs, then you will have to specify your random settings very carefully. With many of the randomized parameters correlated to a single per-particle random number, the combined result can easily produce some unexpected visual patterns and artifacts.

Long Overdue Progress Report

Wow, I can’t believe this blog has been quiet for over six months! Quite a bit longer than I originally intended. I suppose most of my former readers have moved on, but I’ve been doing a lot of Unity effects development again and I hope to return to a higher frequency of posts.

Back in August, I had grown somewhat discouraged with my Unity effects development. My demos were not generating much feedback and I was frustrated with the Unity particle-system. I heard that a new particle-system (dubbed Shuriken) was in the works, so I decided to take a much needed break, not only from my blogging but much of my social networking as well.

Meanwhile, one of the big things I did was team up with a couple of friends from Chicago to develop a novelty audio app for the iPhone called Your Personal Announcer. It was a big change of pace from special effects programming, but I did manage to get my first app fully published in the Apple App Store.

After that it was holiday time and I did a lot of unfocused noodling…

Mapleleaf Frag [WIP]Then around the beginning of the year I got a mention on Twitter from David Helgason and email from Caitlyn Meeks, both encouraging me to create something for the Unity Asset Store. Well, that was some nice and much appreciated feedback and enough to get me to dust off my Unity effects work and look it over with a fresh eye toward turning some of it into one or more Asset Store products.

Since then, I’ve been working a lot on my Unity effects again. The Unity 3.5 public preview (with Shuriken particles) was available, so the timing was good. I carefully went through all my various demos and experiments, condensed them into just a few projects, and have been improving the Effectronica system in a lot of ways. Because I’ve been focusing on consistency and work flow, I don’t have any fancy new demos to share yet, but I’m feeling pretty good about the utility of the overall system again.

One of the challenges to turning Effectronica into a product is that I’m not interested in creating a bunch of canned special effects prefabs. I’m first interested in creating a framework for managing effects that exist within and respond to realistic game contexts. Effects that are constrained to characters and props, and are triggered by user actions and in-game events. Then, with this framework in place, higher-level special effects prefabs can be created to take advantage of it.

Some Unity Demo Videos

I have been posting most of my Unity work in Web Player form, which I think is usually the best way to experience them, but you can’t view these on tablets and smart-phones, and they don’t always work exactly right in certain contexts. So, I went ahead and captured a few demo HD videos and posted them to Vimeo. Here they are:

Bron-Y-Orc Stomp (walking) on Unity from Faust Logic on Vimeo.

Bron-Y-Orc Stomp (running) on Unity from Faust Logic on Vimeo.

Flame Broil spell on Unity from Faust Logic on Vimeo.

Foot Stomping Spell Demo in Unity

Here is another demo of an original Arcane-FX magic spell which I’ve adapted to Unity. This one is the foot-stomping spell, Bron-Y-Orc Stomp, where the spell target takes on super-orc-like powers and wreaks havoc simply by running around and jumping at anything nearby. The spell was actually designed for a bulky orc avatar, and looks a bit silly on the female avatar used her, but oddly enough it comes across quite nicely when the avatar is switched to its walking mode. It gives her swagger some serious attitude.

This is a fairly complicated effect and most aspects of the original spell are contained here. The main thing that’s missing is a number of special blend animations that make the character look more like it’s stomping hard on the ground rather than merely running or walking. This is mainly because I don’t have a rig or proper art-path established for creating new animation for this avatar. I also cut back on some of the vocal utterances that were very unconvincing from this avatar.

I had been working on a new spell dubbed Aether Orrery but I set it aside to adapt Bron-Y-Orc Stomp because I knew it would force the development and testing of some new effect tech I wanted in place. Here are some of the new effect-system capabilities I had to develop to effectively realize Bron-Y-Orc Stomp.

Triggered Effects

Triggered-effects were a powerful capability in AFX, and this spell is built around the concept. The main spell effectron listens to the avatar for footstep and jump-landing triggers. When any occur, it instantiates another effectron that performs the necessary footstep or landing effect. The left and right footstep triggers are generated from Unity Animation Events added to the avatar’s walk and run Animation Clips. The jump-landing trigger is generated by the avatar controller component.

Effect Launch Arguments

There are some prototype systems in place so that effect designers can associate launch arguments with the effectron controlling the effects. At effect launch, these arguments can be assigned unique values that will be rerouted to various properties of the base-effects used. In Bron-Y-Orc Stomp, each triggered footstep and landing effect takes a scale, angle, and sound-clip index argument which shapes how the effects look and sound. By randomly varying these arguments, each triggered effect instance is a little different, creating a more natural effect without artificial repetitions.

Camera Shake, Force Effects, and expanding Projections

This spell required the addition of a few new base-effect types and capabilities. I added a camera-shake effect, which was not difficult, but did require some cleverness to make sure that the camera jitters were applied after the camera-controller moved the camera in response to avatar movement. Force effects were added so that the footsteps and jumping stomps could physically push away any nearby rigid-objects. A Growth Rate property was added to Projector effects for the shock-wave rings. (If you carefully watch the spell in action, you may notice that the projector effects are sometimes cut off by some seams in the terrain. I’m not sure what’s happening here, but it may happen because projectors often get increased in size as part of the effect but their initial size may be getting used to cull them from rendering on different terrain chunks.)

Unity3D Effects Sequencing: Progress Update

Did you see the last Unity Web Player demo that I posted? The one with the female mage casting a fireball spell? If not, you should really check it out:

[ Prototype Fireball Spell in Unity with Effectronica ]
Flamebroil Spell

Overall, I was pretty happy with the end result of this effect demo. The visual effect itself is a pretty decent reproduction of the original Flamebroil from AFX. Also, I managed to get the character’s “making potion” animation to flow convincingly into its spell throwing motion, with a result that is mostly better than the original. It would be almost perfect if the foot positions were not mismatched causing the feet to slide inward for the “making potion” clip. (Separation of upper and lower body animations in the character would greatly help here.)

What I did not like about this demo was all under the hood. Although I think it would have been a lot harder to assemble this effect from scratch, even with help from my effects sequencing components, there was still much tedium to it, especially when fine-tuning the timing. So, after posting this demo, I spent considerable time studying the example, looking for ways to streamline the effect crafting process.

A few simple things helped a lot. I added some menu commands that performed some common multi-step actions automatically and I inserted some important [RequireComponent] directives to force addition of prerequisite components as needed. The tough challenge was dealing with timing edits. Here’s the problem…

A complex multi-effect, like the casting portion of Flamebroil, sequences a number of base-effects (~26) along a common timeline. Timing characteristics are set on a per-effect basis, so they get spread out across multiple Components in multiple GameObjects. When tweaking the timing, you end up jumping all over the place, and have to mostly keep the general relationships in your head. The obvious solution to this is some kind of timeline editing GUI that stacks all the effect lifetimes together allowing you to see and edit their timing relationships directly. Obvious, but not trivial to author in Unity.

To implement something like this I needed to wade into the Unity activity known as “Extending the Editor”.

Now I must say, on most days, I really enjoy using Unity. The editor and the scripting API all make sense to me, I find quick solutions to coding challenges, and I generally feel very productive. But when I start “Extending the Editor”, everything changes. Things that seem easy, don’t work. I find myself wasting hours trying to reproduce GUI behaviors seen in other standard portions of the Editor, sifting through undocumented custom styles, always settling for a compromise. (And I actually like GUI programming.)

Anyway, I eventually came up with a timeline GUI that works, and even though it’s not exactly what I want, it greatly reduces the tedium of effect timeline editing. This is what it looks like:

Timeline Editor

Also, without going into detail at this point, I made good progress researching Unity solutions to these problems:

  • Routing of per-instance centralized effect parameters to specific base-effect properties.
  • Setting per-instance random variations of specific base-effect properties.
  • Triggering base-effects from Animation Events (i.e. footprint effects).
  • Base-effects that alter specific properties associated with other active base-effects.

(Wow, that all sounds rather esoteric. Hopefully you can make some sense out of it. :-| )

EDIT: Oh, and I forgot to mention that I started crafting a brand new effect called Aether Orrery which I’ll demonstrate once it’s a little further along. (Not based on an AFX spell.)

Return top