Layered destruction
Same pillar, same 16 shots on both sides.
Left: the first hit cuts the whole pillar into 78 pieces. Right: tiles chip, concrete goes one chunk at a time, the rebar holds.
The problem
The usual way to make something breakable is to cut the whole mesh into pieces on the first hit. That works for a vase. A tiled concrete pillar goes up in one burst and lands as a pile, no matter where it was shot. Real pillars get chewed away: the tiles crack off first, the concrete goes piece by piece, and the steel inside bends.
How it works
The pillar is built in three layers instead of one mesh:
- Tiles: 320 tiles, 15 cm square and 3 cm thick, on all four faces.
- Concrete core: 16 layers of 3 × 3 cells, about 6 litres each.
- Rebar: 4 bars running the full height.
Each shot is a ray. It stops at the first part still standing:
- A tile: that tile and its neighbours within 13 cm pop off. Nothing behind them breaks.
- A concrete cell: only that cell is cut into convex chunks around the impact point (17 to 27 chunks here), which fly out as rigid bodies.
A layer fails when only 3 of its 9 cells are left. Those 3 are crushed, and everything above becomes one rigid body that drops onto the stump. The rebar is 4 rope joints between stump and top: it can bend, never stretch or snap.
What I hit
At first the debris fell straight through the pillar. Only moving pieces had colliders, so the standing tiles and cells needed static colliders of their own.
When the layer failed, the top didn't move. The crushed rubble jammed the gap and held up 1.5 m of pillar. I let loose debris pass through the falling top. It's a cheat, but rubble that fine wouldn't carry that load.
Spreading the shots over two layers never brought any layer down. Aimed at one band, the layer fails after 6 cell hits.
My build
three.js ConvexObjectBreaker cuts the pieces; rapier.js simulates them at 120 steps per second. Both are unchanged. The breaker uses random cuts, so I seeded it to make both runs repeatable. The layout, hit rules and failure rule are mine. Everything is simulated first and played back for the video. The bent rebar in the gap is drawn as a curve between stump and top; the rope joint only keeps its length.
Trade-offs
- Damage stays where the shots land
- Only the hit cell is cut, so a hit costs little
- Hundreds of parts per pillar to keep track of
- Cells give a blocky grid to the damage
- The failure rule is a simple count, not a stress calculation
When to use it
Shooters and action games with cover that should wear down under fire: pillars, walls, sandbags. Anywhere a single explosion of pieces would look wrong.
Source and credits
Repos:
- github.com/mrdoob/three.js (MIT license), branch dev, commit fa01dd6. ConvexObjectBreaker (examples/jsm/misc) used unchanged; three.js also renders the video.
- github.com/dimforge/rapier.js (Apache-2.0), commit 9f638c5 (npm @dimforge/rapier3d-compat 0.19.3). Rigid bodies, convex-hull colliders and rope joints, used unchanged.
The pillar layout, the hit and failure rules and the hall are my own code. No game assets are used.
Topic credit: @RedefineFX's real-time destruction demo, https://x.com/RedefineFX/status/2117359236040872311. Their code wasn't public; this is a from-scratch browser version.