vfx-hit-spark is a skill from the Summer skill library: a guide your AI agent reads when the task matches, so it builds the good version on the first try. Hit-spark effect: a one-shot burst of additive particles oriented to the surface, fired on impact.
When your agent uses it
- Authoring a hit-spark effect — impact spark, bullet hit, sword clash, ricochet, sparks at a hit point
- Melee hits, bullet impacts, or ricochets have no visual feedback at the contact point
Install
summer setup installs every skill for your agent. To add only this one:
claude-code for your agent, such as codex or cursor. See Skills for every option.
The skill
Tiny stretched additive billboards spraying outward from an impact point, oriented to the surface normal so the burst points the right way. Used for: bullets hitting metal, sword clashes, footsteps on stone, ricochets, lightning endpoints, hammer strikes. The recipe is aGPUParticles3D configured for one-shot bursts plus a spawn_hit_spark(position, normal) static helper that orients the emitter, restarts it, and frees after lifetime.
When to use
- “Sparks when the bullet hits the wall.”
- “Sword clash sparks.”
- “Sparks under the hammer when the blacksmith works.”
- “Footstep sparks on stone for the heavy armor.”
- “Ricochet sparks when the projectile glances off.”
- “Mining: sparks fly when pickaxe hits rock.”
- Endpoint sparks on
vfx-lightningandvfx-muzzle-flashrecipes (they reference this).
When NOT to use
- The user wants a flash at the impact, not a spray of particles — use
vfx-muzzle-flash(recolor it). - The user wants debris chunks (rock pieces, splinters) — those are physics objects, not particles. Spawn
RigidBody3Dshards, then sparks on top. - The user wants water droplets at a water impact — recolor this recipe blue/white (it works) or pair with
vfx-water-ripplefor the ring on the surface. - The user wants persistent burning sparks that linger and cool down — that’s a hybrid; use this for the burst, then tiny
vfx-fireparticles for residual embers.
Recipe
1. Files to create
_building-blocks/additive-billboard-particles.md). A StandardMaterial3D with the right flags is enough. (BaseMaterial3D is abstract: BaseMaterial3D.new() is a parse error. Its enum constants are still the right names to use.)
2. GDScript controller
addons/vfx/hit-spark/hit_spark.gd:
3. Node tree
_ready if missing, so the .tscn can be empty besides the script.
4. Wire it in (MCP calls)
This recipe is a.tscn you instantiate per impact, not added once to the open scene.
Building that .tscn is itself an MCP job — summer_create_scene makes it,
summer_set_prop attaches the script, summer_save_scene writes it out. Every
scene-mutating call takes an explicit scenePath, and summer_set_prop uses key
(not property).
summer_run_script operates on the open scene, and
this recipe builds a standalone hit_spark.tscn — so the summer_create_scene /
summer_replace_node chain above stays the right wiring here. Reach for
scene-scripting only if you are placing many pre-spawned spark emitters
into the open scene with computed positions.
4b. Verify
hit_spark.gd is the whole recipe — if it did not parse, every spawn_hit_spark
call is a no-op.
5. Parameters to tune
Cookbook — named variants
bullet-on-metal (default)
Bright orange, fast, gravity arcs them downward.sword-clash
Wide spray, brief, white-hot.water-droplet
No emission boost, blue-white, gravity-heavy, round dots.blood-spurt
Recolor + heavy gravity. Pair with a small decal on the floor where they land.electric-discharge (paired with lightning endpoints)
Cool blue, low gravity (sparks float briefly), high emission.Anti-patterns
- Forgetting
one_shot = true. Continuous-emission sparks look like a sparkler held still. One-shot + restart pattern is mandatory. explosiveness < 1.0for a one-shot. Particles spawn over the lifetime instead of in frame 1; the burst looks dribbly. Setexplosiveness = 1.0.- Skipping the surface-normal orientation. Sparks always shoot upward regardless of impact direction. The
spawn_hit_sparkhelper handleslook_at+ the −90° rotate-around-X (becauselook_atuses −Z as forward). - Spawning the spark scene as a child of the impacted object. If the object moves or frees, the sparks vanish. Spawn under the scene tree root.
BLEND_MODE_MIXinstead ofBLEND_MODE_ADD. Sparks don’t bloom; they look like flat orange triangles.BaseMaterial3D.new().BaseMaterial3Dis abstract — that line is a parse error and takes the whole script down. InstantiateStandardMaterial3D; keep using theBaseMaterial3D.*enum constants.- Forgetting to free. The
spawn_hit_sparkhelper creates aTimer-equivalent viaget_tree().create_timerto free after lifetime. Otherwise spent emitters accumulate forever. spark_lifetime > 1.0for sharp impacts. Sparks lingering for a full second look like fairy dust. Keep ≤ 0.5 s for snappy hits.
Performance notes
- One burst: 24 particles × 0.35 s = ~negligible. Spawning 60 bursts/sec (full-auto fire) = ~1500 live particles. Still well under the GPU budget.
- For sustained automatic fire, pool the spark instances instead of instantiating per shot. Pre-create 16 spark scenes; round-robin them.
- The
look_at+rotate_object_localpair is the most expensive part of the spawn (one matrix decompose). If you spawn 100/frame, cache the orientation math. - Mobile: drop
spark_countto 12,spark_lifetimeto 0.20.
Edge cases
- Surface normal points exactly UP.
look_atwith up = UP fails. The_safe_uphelper picks RIGHT in that case. - Surface normal is zero (interior trigger volume hit). The function defaults to
Vector3.UPifnormal.length_squared() < 0.0001. - Impact inside a tight space (corner). Sparks penetrate walls visually. Either accept it (additive bloom hides it well) or use a
Decalfor the burn mark and skip particles. - First-person view, sparks from your own gun’s barrel hit. Use a smaller burst (intensity 0.4) so the camera isn’t flooded.
- Networked multiplayer. Spawn sparks client-side based on hit events; never replicate the spark node itself (waste of bandwidth).
- Slow-motion. Sparks freeze gracefully because
Engine.time_scaleslows the particle simulation. No special handling needed.
Fallback (no MCP)
Section 4 is fully automatable —summer_write_file writes the controller and
summer_create_scene + summer_set_prop + summer_save_scene build hit_spark.tscn.
Do not hand these steps to the user when the MCP tools are available.
Without the MCP connection there is no engine to drive, so the user does it
manually in Summer Engine:
- Create
addons/vfx/hit-spark/with the two files above. - Add a
GPUParticles3Dto a new scene, attachhit_spark.gd. Save ashit_spark.tscn. - From any impact handler:
HitSpark.spawn_hit_spark(get_tree().root, position, normal). - Check the Errors dock before wiring the first impact.
Handoff
After firing this recipe, suggest:vfx-muzzle-flash— pair on the gun side; this recipe handles the bullet-impact side.vfx-lightning— automatically calls this at endpoints.vfx-water-ripple— pair thewater-dropletvariant with a ripple ring at the impact for water surfaces.game-feel—CameraShake.add_trauma(0.15)on heavy hits, hit-stop for crit kills.sound-effect— generatemetal-on-metal clang, sharp transient, short ring, 350msper spark variant.
See also
_building-blocks/additive-billboard-particles.md— canonical additive material settings (this recipe uses them)vfx-muzzle-flash— the gun-end companionvfx-lightning— caller; spawns sparks at bolt endpointsvfx-water-ripple— surface companion for water impactsgame-feel— shake/hit-stop pairings
From a shell
No Summer MCP tools in this session? Run each one as a command; whensummer --version is missing or below 4.0, use npx -y summer-engine@latest in place of summer. Fields are flags in kebab-case (--scene-path res://main.tscn) or one --input '<json>', and summer ops describe <op> prints the exact input. The summer-cli skill has the rest.
Files in this skill
Related skills
scene-scripting: Build scenes, levels, HUDs and wiring with one editor GDScript (summer_run_script) instead of call chains.sound-effect: Make sound effects (swings, hits, whooshes, reloads, UI): three versions to pick from, then wire them.game-feel: Add juice: hit-flash, trauma camera shake and audio ducking, one hit fires all three.vfx-fire: Fire effect: animated flames from GPUParticles3D, a particle shader and a noise color ramp.vfx-lightning: Lightning bolt effect: a jagged procedural path with a glow shader, end sparks and screen shake.vfx-muzzle-flash: Muzzle-flash effect: a one-shot ~80 ms burst at a gun barrel, from particles or a star-burst quad.vfx-water-ripple: Water-ripple effect: animated normal-distortion ripples on a water plane or Decal, set off by impacts.
Source:
library/skills/vfx-hit-spark/SKILL.md, rendered from summer-engine@4.3.0 on npm.
