For me, explosions are really important in games. But many games don’t seem to get them right. Sometimes, instead of an earth-shattering plume of smoke and fire, you get a limp, wet flash of some vaguely flame-ish orange stuff. So I’ve been putting some serious thought and effort into designing explosion effects I’m happy with.
Elements of an Explosion
The four central parts of a good explosion in my opinion are fire, smoke, streamers and timing. For a punchy, satisfying effect, I want fire that burns hot, fast, and then turns into dense dark smoke rather than disappearing without a trace. Streamers convey the feeling of something physically coming apart at high speed. Timing is what ties it all together – an explosion has to accelerate hard, then slow down and linger. That’s true of both the central effect and the streamers.
In general, I’m going for stylised rather than realistic. That doesn’t give me free reign – the specific textures and shaders need not be photorealistic, but the critical factors stay the same if I want something that feels right. An important inspiration for me is in fact the kind of explosions often seen in anime; they appear out of nowhere then let you gaze at the aftermath.
Unfortunately, Unity doesn’t really have a shader built in which does what I need, so the first step is to write one. But that’s technical, so its at the end.
With that shader in hand, the central flame and smoke elements are covered by one particle system in Unity. Each particle starts off as flame, and quickly turns into smoke. The particles are emitted at high speed which is quickly damped. Each particle gets bigger very fast as well, then quickly levels out. The emitter acts in two bursts – a small one immediately, then a far larger one 0.15 seconds later. Another anime-inspired choice.
The streamers use the same texture and shader, again with each particle starting as flame and turning into smoke. The emitter is launched from the centre of the explosion in a random direction at high speed and decelerates sharply.
The high speed and rapid deceleration of the explosion and streamers make the effect appear very quickly, then quickly level out and linger for a fast punch and a feeling of solidity afterwards. These are accompanied by a brief flash of light and lens flare at the beginning, lasting less than half a second, to add weight.
After some experimentation, textures with bold, simple colours and fairly homogenous shapes ended up working best (again bearing in mind the stylised look I’m going for). So how does it look?
Not bad. Sound, screen shake and bloom will really help sell it, and I’ll keep tweaking, but I think I’m on the right track.
To create the effect, I needed either a) two emitters combined to have flame first and smoke second, or b) just one with some kind of animation on the particles to have them transform between the two. I also knew I didn’t want additive or multiplicative blending; I needed alpha blending to give the particles opacity and implied density, and emission/self-illumination for the flame. Finally, I wanted the colours of the flame to be set programmatically according to the team colour.
Option a) would give the greatest control, but unfortunately Shuriken, Unity’s particle system, only seems to allow one material per particle system. Creating two separate emitters would be fine with additive or multiplicative blending; but alpha blending needs depth sorting to not look arse, and Unity doesn’t sort particles between separate emitters. All particles from one emitter are either behind or in front of all particles of the other.
Option b), then. The obvious answer is to use a diffuse+alpha+emissive material with an animated texture. Unity supports splitting textures up in a grid and having each particle step through the “frames” over time. However this is a lot of work for my artist, and needs a lot of frames to look smooth. It’s also fairly rigid and means each particle will look fairly similar.
The other problem is that Shuriken is a little limited in how it can manipulate texture colours. It has a single colour parameter, which it can change through a user-specified gradient (in RGB and alpha) over time. It passes this information as vertex colour to the shader. Strangely enough, many of Unity’s built-in shaders, including the diffuse+alpha shader, just throw away vertex colour information without doing anything with it. So straight away I have to write a new shader. And actually, Unity doesn’t have a diffuse+alpha+emissive shader at all!
Fortunately Unity’s “Surface Shader” Cg/HLSL pre-compiler directives make shaders pretty easy for simple shaders. You just specify the pre-existing bits you want to use (alpha transparency, Lambert lighting etc) then write a simple Cg function to specify how the inputs (vertex colour, pre-set colours, textures) are used.
Specifically, I use diffuse for the smoke texture, emissive for flame, and alpha for overall transparency. I want to “animate” from flame to smoke using a single vertex colour time gradient in Shuriken, so I use the RGB component to multiplicatively control the intensity (and optionally colour) of the emissive texture (with the smoke staying constant “underneath”), and the alpha is used separately to fade the entire texture out at the end of its life. I also define a regular input colour which can be set to the team colour in the code. The emissive component is therefore just texture * team colour * vertex colour. This gives me exactly the control I need.
Writing my own shader also has the benefit of letting me define how I want to use texture information. Since the diffuse (smoke), emission intensity (flame) and transparency map textures are all monochrome (with the flame’s actual colour set in code), it makes sense to pack them into a single texture. The diffuse is in red, emission intensity in green and transparency in alpha. I plan to use blue as a hue-shift for the emission, allowing a little more variation rather than a single colour. I haven’t implemented this yet though.
As well as animating through frames, Shuriken can also just give each particle a random grid square as its texture, so I can also have a wide variety of particles with just the one material Shuriken allows.