As the artist of Life Goes On I’m responsible for all the visual effects in the game, which is great because they’re like delicious candy to me. Level design is interesting, level art is pretty rewarding once you’ve slogged through it all, and programming is an inherently fun activity for crazy people like me. Special effects, though, are a special kind of task where all you have to do is make something look cool by using clever tricks. Like many game art tasks it's a fascinating blend of art and engineering and I would do that all damn day if I wasn’t being dragged kicking and screaming back to the tasks that actually need doing. This dev blog is about how I implemented one specific effect in the game that I spent entirely too much time on: the burning death effect!
This effect is played whenever a knight or body get torched by a flamethrower. The flamethrowers completely destroy the knight instead of leaving behind a body that can be used for puzzle solving, and as such they’re a critical obstacle in the game. We decided to take a very cartoony approach to the effect and have the knight freeze in the air Loony Tunes style before dissolving to ash. This would keep in line with the lighthearted tone we wanted for the game, and it’d be fairly unambiguous that the knight's body wouldn't be usable when he burned.
I went through a couple iterations on this one over the course of the project. Check out this video which shows the difference before the first version and the current iteration:
It’s pretty night and day, huh? The first version was pretty quick and dirty, a result of not yet being familiar with Unity and still getting a grip on the whole “3D art” thing. See, about a year and a half ago I somehow managed to con everybody into thinking I was a real artist as opposed to a Computing Science graduate with delusions of grandeur (shh, don’t tell anyone!) so my approach was fairly straightforward and unsophisticated. The original effect involved just turning the knight black, spawning an “ash” particle emitter at every joint, and then destroying the mesh.
While this worked, it has a number of downsides. The first, obviously, is that it’s pretty boring, which isn’t a good quality to have when this effect is going to be played hundreds and hundreds of times. There were also obvious visual hitches, like the knight immediately turning black, and the harsh transition to the particle effect. The particle effect also just didn’t work out as I’d hoped. You can’t use a skinned mesh to spawn particles, so putting a particle emitter on every joint was a workaround that didn't quite do the trick. It didn’t hold the knight's shape, instead turning into an indistinct blob. Finally, I’d envisioned the ash forming into a little pile under the knight, but the particle physics of Unity didn't really support that. They weren’t pulling up in a little cone shaped mound like in the cartoons (that would've been hideously CPU intensive anyhow) and the default physics wants to bounce the particles but I wanted them just to stay put, so they’d jitter and slide around in a way that looked absolutely nothing like ash.
So, when it came time to redo it and bring the visual quality up a notch, I took a step back and asked myself “what exactly do I want this to look like?” In the cartoons, a gigantic gout of flame would envelop the character for a split second, and they’d emerge completely black (except for the eyes) and hang there for half a second before crumbling from the bottom up in complete defiance of gravity. Since the knights of Life Goes On don’t have eyes, those parts of the equation could be ignored. So what I really wanted here is the knight to turn to ash from the bottom up. On the implementation side, that means I wanted the mesh to progressively disappear over time, and the vertices of the mesh should emit particles of ash as they’re hidden.
At this point, I already knew that it was pretty easy to modify a particle system at runtime with a script, so I could make the particles spawn anywhere I wanted if I knew where. That meant that the larger issue was accessing the vertices of the knight’s mesh in whatever pose he was in, which is not something Unity supports. That information is hidden deep within the engine, and isn’t cached for easy access by the scripting engine. I needed to develop a workaround. My initial approach was to just do all the skinning myself, in script, so that I could essentially generate a static mesh from the posed character that I could then process. This was a slow thing to do on the script side, but within a few weeks Unity added a feature that did this within the game engine. It was much faster and much easier, though it made the adventures I had implementing and optimizing my own setup seem a little pointless!
Now I needed to figure out a way to dissolve the knight from the bottom up. I’d already known from the start that I’d probably want to use a shader for this that could make the knight disappear at different rates based off information attached to the vertices, where I would encode height information. I chose to use vertex colours to store this data, but I could just as easily have used a UV2 channel. Using vertex colours required slightly more memory in the mesh, but could take advantage of shader code I’d already written.
This is my "fabrication" shader. This shader would take a floating point parameter from 0-1 such that a value of 0 would have the entire mesh disappear, 1 would have the whole mesh visible, and intermediate values would hide part of the mesh based on the vertex colour (black coloured vertices would disappear first, white ones last). If you had a gradient of vertex colours on the mesh from top to bottom, you could build or dissolve the object from that direction… exactly what I needed.
It did a little more than that, though. It would also put a highlighted, self-lit “rim” along the dividing line between the hidden pixels and the visible ones (it was originally intended for something being fabricated out of nothing, so I wanted it to look like it was being built piece by piece with glowy magic.) I could reuse this with an orange/red colour to look like embers in a campfire as the knight was consumed. I could also hide the uneven vertex transitions in the effect by adding a noise mask to it. The shader would take a mask like this:
And use it to turn the edge of fabrication effect into this:
Which I think looks pretty sweet. For the purposes of the burning effect, though, I wanted something less square and obviously designed. I figured that I could use a rougher looking mask to give it a more dissolve-y effect, so I created this mask:
Which is basically just a Photoshop cloud filter (seriously that thing is MAGICAL) combined with heavily scaled up, blurred noise filter. You can get some very impressive effects just through clever use of filters. Hand drawn masks and textures are great, and there’s a time and place for them, but when you can get the effect you want just by pressing a few buttons it’s a great way to save time!
This mask, when applied to our baked knight model with proper vertex colour assignments, gives an effect like this:
Booyah! Now we’re cooking with gas! This effect is driven in-game with a simple script that modifies the shader’s cutoff parameter in real time, causing the body to burn up from the bottom up.
Next on this list was to have ash stream down from the body as it disintegrated. Having learned a thing or two about particle effects since my previous attempt, I wanted to do this one a little differently. Instead of making the effect out of a whole bunch of tiny, round images that don’t look much like ash, I decided to paint a custom texture for it:
This time the effect used big particles and involved overlapping, rotating particles to give the effect of a billowing cloud. They now hung in the air and slowly descended instead of dropping quickly, and faded into the air as if they were scattering on a breeze. The final effect had a lot more texture and looked more cloud-like than the original ash effect.
Getting it to create the particles on the knight mesh was a bit more difficult. Overriding the spawn position of particles isn’t tough on its own, you just have a script look for particles that are fairly new and change their position. The bigger issue is making sure you select the right vertex on the mesh to spawn on. While we know what range of vertex colour values we want to spawn on at any given time (this syncs up REALLY nicely with the shader values, actually) the vertices themselves do not come sorted, and doing so isn’t cheap. In fact, since there are thousands of vertices to sort through, it’s my biggest performance drain. To get around it, I put the sorting on another thread so it can work while the game keeps running. Because of the comedic pause between the knight be charred and falling apart, I can afford to wait a few extra frames for the values to become available.
Once sorted figuring out what vertices to spawn on is trivial. I do a binary search across the sorted list for the upper and lower values in the range I want, and then just randomly select vertices from between them, which is a reasonable balance for being fast without taking too much of my time programming it. I could be more hardcore about it, I suppose, and optimize based on the fact that anything below the range isn’t going to be used and the next step above the range isn’t likely to be too far up the list, but this isn’t a major performance drain so I didn’t bother.
Now we’ve got the ash particles spawning at the burned up vertices like we wanted!
You’ll also see some sparks amongst the ashes in that image (and in the video at the top of the screen), which are things I just added today. Aside from just looking cool, they also contrast against the ashes to make them more obvious, and to provide a bit of a lingering effect. The ashes on their own are a bit of a subtle effect could get lost in dark scenery, especially since there’s always a big, bright flame in front of them. The sparks help them pop a bit.
There’s a few more little pieces of the effect that help it come together. One is that the knight’s sword doesn’t get tossed aside when he bites it like normal. Instead, it hangs in the air until right about the time that the knight’s hand is being burned up, at which point it drops to the ground comically. This was actually done by Susan, and I think it’s a great little touch that helps sell the effect.
Another little piece is that the knight doesn’t just turn black when he gets fried. There’s a short particle effect that plays in the beginning that partially masks that transition, causing a burst of flame and then a little bit of smoke coming off the knight. This way, he sizzles a little before he falls apart. These particle effects are spawned the same way the knight’s original ash was spawned, by creating particle emitters on the knight’s skeleton. Another little touch, which I just added today, is that the knight actually starts out normal and then has his colour interpolated to black while the flame burst happens, which removes the last trace of hard, jarring transitions from the effect. I actually do this with a separate script that I wrote for generically modifying object’s colours over time. Since the shader for the burning effect implements some of the default parameters Unity uses (in this case, the “_Color” parameter) I can use this generic script to modify my custom shader. Code reuse is great!
So that’s the burning effect, in all its nitty-gritty detail! I hope you found this article useful and interesting. If this has piqued your interest about Life Goes On, head on over to http://lifegoesongame.com/download/ to check out our demo!