mcpField
S
scenario-roblox-vfx-audio

scenario-roblox-vfx-audio

github.com/scenario-labsCreative & media1.2k57 installsUpdated 1d ago
Repository

About scenario-roblox-vfx-audio

A VFX and audio skill for Roblox Studio developers. It builds effects from data-driven templates, supports server-validated client playback, and checks audio graphs with measurements before a person reviews the mix by ear.

Key features

  1. 01Build layered particle, beam, and trail effects
  2. 02Validate effects on the server and broadcast to clients
  3. 03Audit effects and capture them over time
  4. 04Connect audio graphs and measure audibility
  5. 05Create footsteps and music ducking behavior

Use cases

  1. 01Create multiplayer-visible hit and projectile effects
  2. 02Review visual changes across an effect timeline
  3. 03Diagnose disconnected or silent audio graphs
  4. 04Set material-based footsteps and mix music

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/scenario-labs/skills --skill scenario-roblox-vfx-audio

After installing, type/scenario-roblox-vfx-audioin Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

references/
copy-ready.md
critique.md
expert-notes.md
gui-paths.md
procedures.md
sources.md
scripts/
rbx_vfx_audio.py
scripts/agentkit/vfx-audio/
AudioAudit.luau
AudioKit.luau
VfxAudit.luau
VfxKit.luau
scripts/agentkit/vfx-audio/runtime/
Footsteps.luau
FxReplicator.luau

Details

From the project README

Roblox VFX and audio

Target: Roblox Studio (October 2026 build) on macOS, driven through the scenario-roblox-expert toolkit.

Expert effects read in one glance and get out of the way: layered bursts emitted once, decided by the server and drawn by each client. Expert audio is a wired graph proven connected and measured before anyone listens. The agent builds effects as data, freezes and captures them over time, and checks audio through Wire.Connected, GetAudibilityFor and analyzers; a person's ear judges the mix. If a sibling skill named here is missing from your available skills, ask the user to install it (npx skills add scenario-labs/skills --skill <name>); unattended, proceed from tool schemas and flag the gap.

REQUIRED BACKGROUND: scenario-roblox-expert (channels, review loop, toolkit, current-Roblox traps).

Status (2026-10-19): 17 of 17 live tests pass in Studio 0.743 (two on a rerun after MCP timeouts), with playtests, the copy-ready scripts included; 5 of 5 offline checks pass (rbx_check 0 errors on the modules and every snippet, flipbook and audio file checks, Lune arc math). Listening is left to a person.

Stance (the expert delta)

  1. Layers emitted once, not one big sprite. Stack five or more textures (hot spots, a dark underlayer) and emit each once from an EmitCount attribute (Twist VFX, zlKdwujvP2A [00:00:13-00:06:13]; MoldySugar, XXCGWREKpo0 [00:00:29]). Bursts use Emit, lingering tails use Enabled (MoldySugar [00:04:16]).
  2. If you can make out the flash's shape, it lasts too long. Impact flash Lifetime about 0.05 s, slash layers 0.2 to 0.3 s (Twist VFX [00:44:26, 00:00:13]).
  3. Velocity-oriented particles need Speed 0.001 to 0.01, never 0. "If your speed is zero, it'll just disappear" (Twist VFX [00:00:13]). Confirmed: a VelocityPerpendicular particle at Speed 0 drew nothing, at 0.01 it drew.
  4. Beam arcs by rule, not by eye. A semicircle needs CurveSize = chord x 2/3, both ends turned toward the bulge, FaceCamera on, and segments only when it curves (Twist VFX [00:10:55, 00:56:19]). The midpoint then sits at the radius (Beam docs' Bezier, verified live).
  5. The server decides, every client draws. Local effects are seen only locally, so impacts need the server and its raycast (Develuper, TkNZETIu0CM [00:02:15, 00:04:42]). Send the server's decision (name, CFrame, or origin, velocity and server time) to nearby clients and let each clone the template [added]: the server holds no effect instances, clients cull by distance.
  6. A silent world is a missing listener. No AudioListener or AudioDeviceOutput means nothing is heard (Cookie Tech, FminS9nvqJg [00:14:59]). A template place kept DefaultListenerLocation at Default and a playtest had neither (observed). Set Camera once, in Edit.
  7. One Wire per hop, then prove it. n effects need n + 1 wires (ByteBlox, LAYhd_j-thI [00:05:46]; Cookie Tech [00:19:35]). Assert every Wire.Connected and that the source reaches an AudioDeviceOutput; a bad pin name or a cycle reads false (observed).
  8. Footsteps follow the feet. Use footstep animation events with left or right on contact frames and a few material sets, not one looped sound (GnomeCode, PNYtTkMidE8 [00:04:42, 00:08:23]). The default R15 animations carry no markers and the default character sounds are legacy Sounds (observed): keep a stride fallback and mute or replace Running.

Establish first

  • Who must see each effect: the caster only (feedback, drawn at once) or everyone near (validated by the server).
  • Devices: mobile caps each emitter at 100 particles per second and drops flipbooks on low memory (particle emitters docs).
  • References: clips of the look; experts build from references, not from scratch (Twist VFX [00:49:09]).
  • Audio stack: Audio API for new work; legacy Sound stays for existing games (not deprecated, deltas row 21). Voice chat on or off.
  • Assets: built-in stand-ins, or uploaded IDs. Uploads are a human step (Asset Manager, from the Window menu or the Home tab); the agent prepares and checks files.

Defaults: templates in ReplicatedStorage.FxLibrary, a workspace.Fx folder for live copies, DefaultListenerLocation Camera, AgentKit modules synced with sync_runtime.

Procedure

Without the kit (an answer, or a game that does not ship it), use the standalone scripts in copy-ready.md: replicator, audio graph, marker footsteps, one-player post effects, Highlight hit flash, lag test.

  1. Set up the place. VA.sync_runtime(studio) writes VfxKit, AudioKit, FxReplicator and Footsteps as ModuleScripts; set DefaultListenerLocation to Camera (listener setup). GATE: modules present; AudioAudit.audit(game) reports no no-listener.
  2. Build templates as data. One VfxKit.build spec per effect: emitter, beam, trail, light and sound layers, timing in attributes (templates). Set LightInfluence and textures explicitly. GATE: VfxAudit 0 errors, 0 warnings (audit).
  3. Review over time. VA.timeline freezes the effect at chosen times with TimeScale 0 and captures each; open the contact sheet and judge it with critique.md. GATE: image_checks pass, consecutive frames differ, readable silhouette in the first frame, nothing left in the last.
  4. Replicate. FxReplicator.server validates type, cooldown and range, raycasts, and broadcasts; FxReplicator.client plays and culls (replication). GATE in a playtest: server workspace.Fx stays at 0 children, client copies return to 0 after lifetime(), spam and out-of-range requests are rejected, play captures show the projectile and its trail.
  5. Wire the audio. Buses are AudioFaders into one AudioDeviceOutput; effects go in with AudioKit.chain; 3D sources are AudioEmitters on Attachments (audio graph). GATE: all wires connected, AudioKit.paths reaches AudioDeviceOutput, IsPlaying and TimePosition move, an analyzer reads a level, GetAudibilityFor matches the intended curve.
  6. Mix behaviors. Duck music under hits with an AudioCompressor Sidechain (ducking); footsteps by marker or stride (footsteps). GATE: measured reduction in dB; steps per distance and the set per floor material.
  7. Hand the ear pass to a person. List what only a human can judge (critique.md, ear items) with the exact place and timestamps to listen to.

Numbers

ValueNumberRelative to, source
Emitter rate cap400 per s; 100 per s on mobileper emitter (docs)
Particle lifetime cap20 sengine (docs)
Impact flashLifetime about 0.05 sTwist VFX
Slash layerLifetime 0.2 to 0.3 s, Speed 0.001 to 0.01Twist VFX
ZOffset between layers0.001Twist VFX [00:02:24]
Beam semicircleCurveSize = chord x 2/3 (20-stud chord: 13.33, apex 10)chord length (Twist VFX; live)
Curved beam segmentsup to about 50; Instance.new gives 10curvature (Twist VFX; observed)
Beam texture repeatsStretch: TextureLength times; Wrap and Static: length / TextureLengthbeam length (Beams docs)
Flipbook sheet1024 x 1024; 2x2, 4x4 or 8x8; at most 30 fpsper texture (docs)
Audio importunder 20 MB, under 7 min, at most 48 kHz; mp3, ogg, wav, flacper file (docs)
AudioCompressorThreshold -60 to 0 dB, Ratio 1 to 50, Attack 0.0001 to 0.5 s, Release 0.01 to 5 sreference
AudioFader Volume0 to 3reference
Default emitter rolloffabout 4 / distance: 0.133 at 30 studs, 0.044 at 90GetAudibilityFor (observed)
Footstep strideabout 4.4 studsdefault R15 run at WalkSpeed 16 (observed)
Footstep volumes0.3 grass, 0.5 defaultper material set (GnomeCode [00:08:23])
Ducking startThreshold -30 dB, Ratio 8, Attack 0.01 s, Release 0.3 s[added]; measured -21 dB on the music (test L8)
Loudness targetsmusic -16 LUFS, true peak -1.5 dB; one-shots peak -1.5 dBFS[added]

Quality gates

  • Measurable: VfxAudit and AudioAudit clean; every Wire.Connected; paths() reaches the output; analyzer RmsLevel above 0 while playing; server holds no effect instances; client copies back to 0; footstep counts per distance; audio files pass check_audio, sheets pass check_flipbook.
  • Visual: freeze-frame contact sheets in Edit, play captures over time from a fixed camera, judged with critique.md. Raise Studio's Editor Quality Level before judging (File > Studio Settings > Rendering; MoldySugar, 9dQR7FySSLg; gui-paths.md).
  • Ear (human only): balance, timing against the picture, tone, repetition fatigue, clipping by ear.

Common mistakes

MistakeSymptomFix
Speed 0 on a velocity-oriented emitterthe particle never showsSpeed 0.001 to 0.01
Brightness raised at LightInfluence 1no change (observed: 1 and 6 identical)LightInfluence below 1 (TrendyV2, rIXyQ4RAwws [00:02:35])
Emitter made with Instance.newLightInfluence 0 (observed) while a Studio insert gives 1 (docs)set LightInfluence explicitly
Trail or Beam with one attachmentnothing drawnset Attachment0 and Attachment1
Effect cloned on the serverdoubled effects, network cost, no cullingbroadcast, clone on clients
Sound parented to a SoundGroupgroup volume ignoredset Sound.SoundGroup (docs)
AudioPlayer.AssetIddeprecatedAudioPlayer.Asset
AudioEmitter under a Folder or Modelsilentparent to an Attachment, a part or the Camera
Listener left at Default3D audio silent in playDefaultListenerLocation Camera
Footsteps from MoveDirectionno steps under Humanoid:MoveTo (observed)root velocity
Built-in explosion01_smoke_main or fire_sparks_main as a stand-inlayer invisible: the texture is near black (observed)smoke_main.dds, SquareParticle.png
Editing ModuleScript.Source in Editold code still runs (observed)replace the ModuleScript instance

Handoffs

  • From scenario-game-assets and scenario-sprite-animation: VFX textures and flipbook frames (2x2, 4x4 or 8x8 grids). Pack with make_flipbook, check with check_flipbook, then a person uploads.
  • From scenario-audio and scenario-elevenlabs: sound effects, music, voice. Run prepare_audio (trim, 48 kHz, level) and check_audio, then a person uploads.
  • From scenario-roblox-animation: footstep and hit-frame markers on animations.
  • From scenario-roblox-gameplay: hit events, projectile id, origin and velocity; this skill draws them.
  • With scenario-roblox-networking: remote validation and rate limits for effect requests.
  • To scenario-roblox-environment: ambient beds and the lighting effects read against. Lighting recipes live there: warm light with cool shadows (aq0Fi0R2FAY [00:03:38]), Bloom Threshold about 0.03 (aq0Fi0R2FAY [00:07:37]).
  • To scenario-roblox-performance: emitter, beam and flipbook counts per scene for the frame budget.

Current Roblox notes

  • Audio API is general since 2024-09-10; AudioPlayer.Asset replaces AssetId; AudioPlayer's internal volume doubled in 2025: recheck old levels (deltas row 21).
  • The reference property is SoundService.DefaultListenerLocation (plugin security: set it in Edit).
  • FlipbookIncompatible reads "Particle texture must be 1024 by 1024 to use flipbooks." with layout None and on sheets that animate (observed): a hint, not a status.
  • An EditableImage set as a particle's TextureContent drew nothing, while the same image drew on a Decal (observed): preview sheets on a Decal.
  • Lighting.Technology is superseded; lighting belongs to scenario-roblox-environment.

References

Comments

Markdown supported