I've been working on a little voxel-based mobile game, a game with plenty of explosions... and I thought it would be cool if stuff could explode into their constituent cubes.
The game has a lot of "explodable objects" in different sizes and with different colour makeup. All of the objects have both a diffuse and emission texture. I wanted emissive parts of the object to explode into emissive cubes. I also wanted all of the cubes generated in the explosion to be emissive at first, and then fade to their default state, to simulate a burst of heat.
The solution consisted of:
- Use object pooling, for the obvious performance reasons, but also because we want to pre-calculate some stuff for the explosions on awake.
- Explode stuff using a particle system, from a volume that roughly matches the shape of the object, into cubes, with colours that match the object, and with the aforementioned emissive properties.
- Make a shader based on vertex colours to support the above
Pooling is simply keeping the gameobjects in the world and using "SetActive" instead of Instantiate/Destroy. It saves precious mobile CPU cycles, prevents garbage collection, and since we want to do some expensive precalculation on each object, it's basically mandatory. All the precalculation is done on awake, before we render the first frame in the scene.
Setting up the particle system (and collider too)
We'll attach a script to our explodable gameobject. Each explodable object has a rigidbody and box collider, a child object with a mesh + renderer for the non-exploded version, and a child object with a particle system for the exploded version.
The particle system has:
- a zero particle emission rate
- a single burst configured with 1 cycle only (the explosion)
- A shape of "Box"
- Renderer set to Mesh: Cube
Setup code below. We're simply setting the size of our particle system, and the number of particles it produces, based on the size of our game object.
Mapping texture mapped colours to particles
This assumes the shader you are using has maps called _MainTex and _EmissionTex.
Here we load up the material used by the mesh we want to load, traverse the UV coordinates, go find the corresponding pixel in the texture map for each UV, and store the colour found along with how many occurences of that colour were found.
Once we have the weights, we extrapolate that into a lookup table for our particle system.
In order to render our particles in the appropriate albedo colours, and with the appropriate emission, we'll need to write our own shader based on vertex colours.
This is a standard lit surface shader. It should be assigned to a material and assigned to the explosion particle system's renderer.
Colourize the particles
We're colourizing in late update. If the explosion has been triggered, then the particles will be available for us to modify here, and need to be modified just once.
Setting the particle colour literally just sets the vertex colours on the particle, and won't be visible without an appropriate vertex colour shader like the one we just made.
Here we also pass in the _ElapsedTime value for our fading emission.
"Blow Stuff Up"
The trigger, and the reset for repeated explosion fun times.
Whilst I am an experienced (mostly non-game) developer, I have only been developing in Unity for a short while. I'm currently working on my first commercial game in 17 years.
I'm able to generate multiple explosions at once on my 4 year old test device, in-game, and maintain a locked 30fps. There is still headroom for more optimisation. Using an unlit shader should see big performance gains.
If you learned something, I'd be very grateful if you could email it to a friend, or share it on Twitter or Facebook. Thankyou!