impact
What a round does where it lands. A flash goes off at the point of impact and a burst is thrown back along the surface normal — and what that burst is comes from the surface it hit, not from a colour parameter.
local hit = physics.raycast(muzzle.position, aim, 200)
if hit then
effects.play("@builtin::systems.effects.combat.impact", {
position = hit.point,
params = { normal = hit.normal, surface = "metal" },
})
end
normal takes exactly what a cast reports: every physics.raycast /
raycastAll / raycastScreen / sphereCast hit carries { entityId, point, normal, distance, startedInside }, so the point goes to position and the
normal goes to normal.
The surface it hit
surface is the parameter that makes this an impact rather than a burst. It is
an enum, so it takes one of a closed list of names and a name outside that list
raises and reports the ones that are in it.
surface | What it throws |
|---|---|
metal | 36 hot sparks at 9 m/s, no dust, a full-strength flash. Low drag and hard gravity, so they arc away and settle. |
stone | 16 pale chips and a 26-particle grey dust cloud, at a little over half the spark speed, with a flash at 40%. |
dirt | No sparks at all, a 46-particle brown cloud at a third the speed, and a flash at 8%. |
wood | 12 tan splinters and 18 pale dust, with a flash at 15%. |
Each row sets spark count, dust count, colour, speed, drag, gravity, particle
size, how long the burst lasts and how bright the flash is. count, speed,
spread and lifetime then scale the row the surface chose, so a big soft
strike on dirt and a small hard strike on metal are the same asset.
Parameters
| Parameter | Type | Default | Range | What it changes |
|---|---|---|---|---|
normal | vec3 | {0, 1, 0} | world space | The surface normal at the point of impact — a cast's normal. The burst is thrown back along it. |
surface | enum | metal | metal, stone, dirt, wood | Which profile above the burst comes out of. |
count | number | 1.0 | 0.0 – 4.0 | How much the surface throws, as a multiple of its profile. At 0 nothing is thrown and no emitter is leased. |
spread | number | 0.45 | 0.0 – 1.0 | How wide the burst opens around the normal — 0 is a tight jet, 1 the whole hemisphere. |
speed | number | 1.0 | 0.05 – 4.0 | How fast the burst is thrown, as a multiple of the profile. |
lifetime | number | 1.0 | 0.1 – 4.0 | How long the burst lasts, as a multiple of the profile. It is also the effect's own length. |
Cost
<!-- cost: quoted verbatim from effect.yaml -->| gpuMs | vramBytes | measuredOn |
|---|---|---|
| 0.01 | 31524 | see effect.yaml |
The size is what the effect's own backends report they hold at a representative
instant — handle:stats().bytes — read identically on every engine, in every
scene and on every repeat. The emitter vertex buffers an effect draws from come
out of a pool shared across the process that grows in chunks, so a
renderer.gpuMemory() delta taken around one play is that pool's growth as much
as the effect's; what those buffers cost at the declared slot counts is below.
The span is the median of five interleaved idle/loaded windows of the frame's
measured GPU pass sum, which read 0.000 ms with a spread of about 0.008 ms: the
effect costs less GPU time than that instrument resolves, and 0.01 is the bound
the reading supports.
Measured on metal at the declared defaults: 31,524 bytes of emitter simulation
state, plus 27,360 bytes of emitter vertex geometry — the spark emitter's 36
quantised slots at 760 bytes each. Slot counts are quantised in twelves so a
spread of count values lands in a handful of pool buckets rather than one per
value, and a surface that also throws dust leases a second emitter and spends
its own slots on top.
What it draws with
| Asset | Role |
|---|---|
combat/materials/combat_glow | the family's one additive material — the flash |
combat/glow | the module that leases the flash card and writes its lanes |
The sparks and the dust are particles rather than geometry, so the only thing the shared material draws here is the flash itself.
See also
@builtin::systems.effects.combat.tracer— the round that lands here.@builtin::systems.effects.combat.shockwaveRing— the front a larger blast pushes out from the same point.guides { path: "topics/physics" }— the casts that report a hit's normal.
Scoped to this part · feeds back into the world's score.