projectrtsunitygame developmentdevlogvfxparticlessmokegpuperformancework in progress

Dev Diary #8: My Own Effects, From Flat Pictures to Live Smoke

October 10, 2026
5 min read

In this part, I'm going to talk about effects: explosions, smoke, fire, muzzle flashes, dust, and sparks. I replaced them entirely in the game, and along the way I had to change my approach three times. Let me note right away: all measurements were taken on one machine, in a test build, and in a single battle scene. I haven't tried these effects with live players yet, and at the end there's a list of what's still unfinished.

Where I started

The game's previous effects were built from procedural textures: noise and soft circles. They look like balls, and the explosion I had was a dark, shapeless soft blob. I needed something closer to what's done in Niagara or Houdini, so I decided not to pick ready-made sets, but first to test how far I could get from this starting point.

Dev Diary #8: My Own Effects, From Flat Pictures to Live Smoke — 1

The screenshot shows four stages one second after the explosion. Top left is the old effect, top right is a flipbook, bottom left is volumetric smoke, bottom right is a live simulation. The camera and timing in the frames don't match completely: the last frame was captured 1.2 seconds in and lower down, so the height of the column is visible.

Flipbooks

The first step was flipbooks: a ready-made free explosion simulation is baked into an atlas of frames, and those frames are played on flat quads. The result was much better than before. The in-game camera looks down at an angle of 40 to 68 degrees and rotates, so the edge of the quad is visible, and the silhouette is the same from all sides.

Dev Diary #8: My Own Effects, From Flat Pictures to Live Smoke — 2

The screenshot shows the smoke at this stage: the shape is flat, and the edge is grainy, as if it were cut out with a mask. That's exactly what I didn't like.

Volumetric smoke

I decided to abandon Unity's particle system because it doesn't let you control everything that's needed, and to build my own. The first step was this: the ready-made smoke simulation is stored not as frames, but as a 3D texture, and the smoke is rendered by rays passing through it. That gave the smoke volume: you can move the camera around it and see it from any side. But this stage also had complaints: the effects are volumetric in fact, but visually flat, and there's not enough depth.

My own smoke and fire simulation

Next, I built a solver that computes smoke and fire on the GPU: a grid of up to 256 cells along the long side, with velocity and density in each cell, like Houdini Pyro. For the game, the result can be baked into a volume, which is cheap, and large effects can be played live. My own solver is more convenient than a pre-made simulation because you can get as many variations as you want, not just one.

Dev Diary #8: My Own Effects, From Flat Pictures to Live Smoke — 3

The screenshot shows the same smoke column before and after volume rendering quality tweaks. On the right, the smoke is darker inside, folds are visible, and a shadow lies on the ground.

Dev Diary #8: My Own Effects, From Flat Pictures to Live Smoke — 4

The clip shows three explosions in a row in a live simulation.

Particle engine and editor

One simulation isn't enough for the game, you also need flashes, sparks, tracers, debris, decals, and light. So I built a universal effects engine rather than individual effects. Particles are computed on the GPU, with up to 130,000 in a single pool. An effect consists of emitters, and each emitter is a stack of modules, like in Niagara: spawning, change over lifetime, forces, collisions, rendering. You can render with sprites and ribbons, meshes, volumes, decals, and light, plus camera shake and sound.

Dev Diary #8: My Own Effects, From Flat Pictures to Live Smoke — 5

The screenshot shows the effects editor window. On the left is the effects library by folders, in the center is an explosion preview with a timeline, on the right is the module stack of the selected emitter, and above the preview is a line with GPU timing per pass. In the measurement, 50,000 particles being added in a single cloud cost about 0.09 milliseconds of GPU time.

Effects in the game

The new engine is now connected to the game. The set consists of 74 effects: explosions of various sizes, hits by armor class, muzzle flashes by caliber, unit and building deaths, etc. The old system remains as a fallback: there's a "New effects" toggle in the graphics settings. Weather now affects effects: wind carries particles and smoke, and rain extinguishes fire and dust.

Dev Diary #8: My Own Effects, From Flat Pictures to Live Smoke — 6

The screenshot shows a battle in the game: tracers, muzzle flashes, fire, and smoke on burning vehicles. The map in this frame is dark because of a sun setting error I haven't fixed yet, and it's not related to the effects.

When I looked at the effects in the game, I immediately disliked their sizes: hits and explosions were too long and too big. So I introduced standards. A hit is no larger than a unit and no longer than 0.8 seconds, a shell or vehicle explosion is about 2.5 seconds and 6 units in size, etc. All effects are adjusted to these standards at build time, and there's a test that checks that none of them go out of bounds.

Dev Diary #8: My Own Effects, From Flat Pictures to Live Smoke — 7

The clip shows, in slow motion, smoke from a destroyed building.

How much it costs

I measured the cost of effects in battle: two armies at the center of the map, about 110 units and two buildings, 1920x1080 resolution, test build, RTX 4070 Laptop GPU. The game has four effect quality levels, from Low to Ultra: the higher the level, the more particles and light sources, and on Ultra the smoke is computed as a live simulation.

Dev Diary #8: My Own Effects, From Flat Pictures to Live Smoke — 8

The graph shows the added GPU frame time. The old effects cost 0.6 milliseconds, and the new ones on High cost 3.2 to 3.4, which fits within the 3 to 4 millisecond budget I set for myself (the blue bar). The whole frame grew from 9.5 milliseconds without effects to 14.2 to 14.5 on High, because part of the cost isn't on the GPU.

What's unfinished

Fog of war doesn't yet reach the particle shaders: effects are culled based on whether the cell is explored, and then fog is drawn on top. When effects have lights, about 3 kilobytes per frame of garbage remains in memory in the test build, and that needs to be investigated with a profiler. Flipbooks don't yet have six-way lighting, etc. I'm not deleting the old effects: they remain as a fallback until the new ones pass playtests.

What's next

Next, I want to test the effects on maps with different seasons and weather, then run a playtest, and only after that remove the old system. Fog of war for particles remains a separate task.