[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6KRCF5BNAC1HPD8C62ZF65E":3,"skill-same:01M6KRCF5BNAC1HPD8C62ZF65E":88},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":30,"linkOnly":31,"markdownContent":32,"markdownBody":33,"frontMatter":34,"refName":35,"commitSha":36,"skillDirectory":37,"forksCount":38,"repositoryHtmlUrl":39,"repositoryHomepageUrl":6,"ownerHtmlUrl":40,"ownerBlogUrl":41,"ownerDescription":42,"updatedAt":43,"install":44,"resources":57},"01M6KRCF5BNAC1HPD8C62ZF65E","particles-vfx",null,"Use when implementing particle effects — GPUParticles2D\u002F3D, ParticleProcessMaterial, emission shapes, subemitters, trails, attractors, collision, and common VFX recipes","jame581\u002FGodotPrompter","jame581","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F21112138?v=4","01M6KR3KEQ9Z30WVJRR2E2ZVXE","Jan Mesarč","01M6KR3KJVRMPDSMASQPBCBVK3",962,"MIT","https:\u002F\u002Fgithub.com\u002Fjame581\u002FGodotPrompter\u002Fblob\u002Fmaster\u002Fskills\u002Fparticles-vfx\u002FSKILL.md",[],[19,20,21,22,23,24,25,26,27,28,29],"particles","particles vfx","vfx","3D","implementing","use","effects","common","trails","recipes","when","2026-11-10 10:12:30",false,"---\nname: particles-vfx\ndescription: Use when implementing particle effects — GPUParticles2D\u002F3D, ParticleProcessMaterial, emission shapes, subemitters, trails, attractors, collision, and common VFX recipes\n---\n\n# Particle Systems in Godot 4.3+\n\nAll examples target Godot 4.3+ with no deprecated APIs. GDScript is shown first, then C#.\n\n> **Related skills:** **shader-basics** for custom particle shaders, **3d-essentials** for lighting and environment that affect particles, **2d-essentials** for 2D rendering context, **tween-animation** for code-driven VFX timing, **godot-optimization** for particle performance tuning.\n\n---\n\n## 1. Core Concepts\n\n### GPU vs CPU Particles\n\n| Node                | Processing | Features                                | Use For                        |\n|---------------------|------------|-----------------------------------------|--------------------------------|\n| `GPUParticles2D`    | GPU        | Full features, high counts, trails      | Most 2D effects                |\n| `GPUParticles3D`    | GPU        | Full features, attractors, collision    | Most 3D effects                |\n| `CPUParticles2D`    | CPU        | Simpler, no trails\u002Fattractors           | Low-end devices, few particles |\n| `CPUParticles3D`    | CPU        | Simpler, no trails\u002Fattractors           | Low-end devices, few particles |\n\n**Rule of thumb:** Use GPU particles by default. Switch to CPU particles only for low-end\u002Fweb targets. Neither node exposes per-particle positions to scripts, so spawning objects at particle locations needs your own simulation.\n\n> You can convert between GPU and CPU particles in the editor: select the node → toolbar → **Convert to CPUParticles2D\u002F3D** (or vice versa).\n\n### Particle System Architecture\n\n```\nGPUParticles2D\u002F3D\n├── Process Material (ParticleProcessMaterial)   ← physics, emission, color\n├── Draw Pass 1 (Mesh)                            ← what each particle looks like\n└── (Optional) Draw Pass 2-4                      ← additional meshes\n```\n\n### Minimal Setup\n\n1. Add a **GPUParticles2D** (or 3D) node\n2. In Inspector → Process Material → **New ParticleProcessMaterial**\n3. Set **Amount** (number of particles)\n4. Configure emission, direction, velocity, gravity\n5. (2D) Set **Texture** for particle appearance\n6. (3D) Set **Draw Pass 1** mesh (QuadMesh for billboards, or custom mesh)\n\n---\n\n## 2. Key Node Properties\n\n### GPUParticles2D\u002F3D Properties\n\n| Property          | Type     | Description                                         |\n|-------------------|----------|-----------------------------------------------------|\n| `emitting`        | `bool`   | Start\u002Fstop emission                                 |\n| `amount`          | `int`    | Total particles alive at once                       |\n| `lifetime`        | `float`  | Seconds each particle lives                         |\n| `one_shot`        | `bool`   | Emit once then stop                                 |\n| `preprocess`      | `float`  | Simulate this many seconds before first frame       |\n| `speed_scale`     | `float`  | Time multiplier for particle physics                |\n| `explosiveness`   | `float`  | 0.0 = spread over lifetime, 1.0 = all at once      |\n| `fixed_fps`       | `int`    | Lock particle update rate (0 = match render FPS)    |\n| `local_coords`    | `bool`   | Particles move with the node (true) or stay in world (false) |\n| `draw_order`      | `enum`   | Index, Lifetime, or Reverse Lifetime                |\n| `amount_ratio`    | `float`  | Fraction of particles to emit (0.0–1.0)             |\n\n### One-Shot vs Continuous\n\n```gdscript\n# Continuous emitter (fire, smoke, ambient dust)\n$GPUParticles2D.one_shot = false\n$GPUParticles2D.emitting = true\n\n# One-shot burst (explosion, impact splash)\n$GPUParticles2D.one_shot = true\n$GPUParticles2D.emitting = false  # arm it\n# Later, trigger:\n$GPUParticles2D.restart()\n$GPUParticles2D.emitting = true\n```\n\n```csharp\n\u002F\u002F Continuous\nvar particles = GetNode\u003CGpuParticles2D>(\"GPUParticles2D\");\nparticles.OneShot = false;\nparticles.Emitting = true;\n\n\u002F\u002F One-shot burst\nparticles.OneShot = true;\nparticles.Emitting = false;\n\u002F\u002F Trigger:\nparticles.Restart();\nparticles.Emitting = true;\n```\n\n### Local Billboard Alignment (Godot 4.7+)\n\n`GPUParticles3D` gains `TRANSFORM_ALIGN_LOCAL_BILLBOARD` (`= 4`): each particle's Z axis faces the camera while preserving a given axis — X or Y, chosen via `transform_align_axis`. For billboarded particles, `transform_align_channel_filter` selects which custom channel to read to calculate their angle. `ParticleProcessMaterial` pairs this with per-axis rotation velocity: enable `use_rotation_velocity_3d`, then set `rotation_velocity_3d_min\u002Fmax` (`Vector3`, on the particle's local axes) and optionally `rotation_velocity_3d_curve` (per-axis curve over lifetime).\n\n```gdscript\n# 3D only — billboard toward the camera while keeping the Y axis fixed.\n# Assumes a ParticleProcessMaterial is assigned (section 1 setup).\n$GPUParticles3D.transform_align = GPUParticles3D.TRANSFORM_ALIGN_LOCAL_BILLBOARD\n$GPUParticles3D.transform_align_axis = RenderingServer.PARTICLES_ALIGN_AXIS_Y\n\nvar mat: ParticleProcessMaterial = $GPUParticles3D.process_material\nmat.use_rotation_velocity_3d = true\nmat.rotation_velocity_3d_min = Vector3(-2.0, 0.0, 0.0)\nmat.rotation_velocity_3d_max = Vector3(2.0, 0.0, 0.0)\n```\n\n```csharp\n\u002F\u002F Assumes a ParticleProcessMaterial is assigned (section 1 setup).\nvar particles = GetNode\u003CGpuParticles3D>(\"GPUParticles3D\");\nparticles.TransformAlign = GpuParticles3D.TransformAlignEnum.LocalBillboard;\nparticles.TransformAlignAxis = RenderingServer.ParticlesTransformAlignAxis.Y;\n\nvar mat = (ParticleProcessMaterial)particles.ProcessMaterial;\nmat.UseRotationVelocity3D = true;\nmat.RotationVelocity3DMin = new Vector3(-2.0f, 0.0f, 0.0f);\nmat.RotationVelocity3DMax = new Vector3(2.0f, 0.0f, 0.0f);\n```\n\n---\n\n## 3. ParticleProcessMaterial — Essential Properties\n\nThe material drives per-particle behavior: **emission shape** (Point \u002F Sphere \u002F Box \u002F Ring \u002F Points \u002F Directed Points), **direction + spread + initial velocity**, **gravity**, **scale and color over lifetime** (via `scale_curve` \u002F `color_ramp`), **damping**, **radial\u002Ftangential acceleration**, and **angular velocity**.\n\n> See [references\u002Fprocess-material-basics.md](references\u002Fprocess-material-basics.md) for the emission-shape table and GDScript + C# snippets for each property group.\n\n### Per-Axis 3D Scale & Rotation (Godot 4.7+)\n\nRandomize scale and initial orientation per axis instead of uniformly. `use_scale_3d` enables `scale_3d_min\u002Fmax` (`Vector3` random scale per particle); `use_rotation_3d` enables `rotation_3d_min\u002Fmax` (`Vector3`, degrees — works only in 3D).\n\n```gdscript\nmat.use_scale_3d = true\nmat.scale_3d_min = Vector3(0.5, 1.0, 0.5)\nmat.scale_3d_max = Vector3(1.0, 2.0, 1.0)\n\nmat.use_rotation_3d = true  # 3D only\nmat.rotation_3d_min = Vector3(0.0, -180.0, 0.0)  # degrees\nmat.rotation_3d_max = Vector3(0.0, 180.0, 0.0)\n```\n\n```csharp\nmat.UseScale3D = true;\nmat.Scale3DMin = new Vector3(0.5f, 1.0f, 0.5f);\nmat.Scale3DMax = new Vector3(1.0f, 2.0f, 1.0f);\n\nmat.UseRotation3D = true;  \u002F\u002F 3D only\nmat.Rotation3DMin = new Vector3(0.0f, -180.0f, 0.0f);  \u002F\u002F degrees\nmat.Rotation3DMax = new Vector3(0.0f, 180.0f, 0.0f);\n```\n\n### Inheriting Emitter Scale (Godot 4.7+)\n\n`particle_flag_inherit_emitter_scale` (default `false`): if `true`, particles inherit the scale of the emitter node. Has no effect when `local_coords` is `true`, since particles in local space are already affected by the emitter's scale.\n\n```gdscript\nmat.particle_flag_inherit_emitter_scale = true\n```\n\n```csharp\nmat.ParticleFlagInheritEmitterScale = true;\n```\n\n---\n\n## 4. Common VFX Recipes\n\nThe recipes most projects need: **fire** (2D, looped emission with hot-color gradient + scale-down), **explosion burst** (one-shot, high-amount short-lifetime), **dust \u002F footstep puff** (one-shot, scale-up + rapid fade).\n\n> See [references\u002Fvfx-recipes.md](references\u002Fvfx-recipes.md) for ready-to-use GDScript wiring and recommended `ParticleProcessMaterial` settings for all three.\n\n---\n\n## 5. Trails (Forward+ and Mobile only)\n\nSet `trail_enabled = true` on `GPUParticles2D\u002F3D` and assign a `Mesh` (`RibbonTrailMesh` or `TubeTrailMesh`). Trails are NOT supported in the Compatibility renderer.\n\n> See [references\u002Ftrails.md](references\u002Ftrails.md) for the setup and trail-mesh-type comparison.\n\n> **Godot 4.8+:** `Trail3D` (inherits `LineBase3D`) draws a flat line behind a moving object without particles, such as a sword swing or a projectile. Size it with `width` \u002F `width_curve`, and limit it by `lifetime` (default 0.2 s) or `max_length` through `limit_mode`; `mesh_alignment` picks a 3D line or a billboard. `color` \u002F `color_gradient` only show when the material uses vertex color as albedo.\n\n---\n\n## 6. Subemitters\n\nA particle can make another particle system emit at a constant rate, at collision, at its death, or (Godot 4.4+) at its birth. Configure via `ParticleProcessMaterial.sub_emitter_mode` + the `sub_emitter` property on the parent particles node.\n\n> See [references\u002Fsubemitters.md](references\u002Fsubemitters.md) for trigger modes, scene setup, GDScript and C# (v1.6.0 parity), and limitations.\n\n> **Note:** With `sub_emitter_keep_velocity = true` (default `false`), subemitted particles inherit the parent particle's velocity when they spawn. This is unchanged in 4.7: a regression in 4.7 dev builds that broke the inheritance was fixed before 4.7 stable ([GH-118062](https:\u002F\u002Fgithub.com\u002Fgodotengine\u002Fgodot\u002Fpull\u002F118062)), so nothing needs migrating from 4.6.\n\n---\n\n## 7. Attractors & Collision (3D)\n\n`GPUParticlesAttractor*3D` (Box \u002F Sphere \u002F Vector Field) pulls particles toward a region. `GPUParticlesCollision*3D` (Box \u002F Sphere \u002F SDF \u002F HeightField) lets particles bounce off geometry. Compatibility runs box\u002Fsphere attractors and box\u002Fsphere\u002Fheight-field colliders; vector-field attractors and SDF colliders need Forward+ or Mobile. 2D has no attractor nodes, but `GPUParticles2D` collide with `LightOccluder2D` nodes when `collision_mode` is set.\n\n> See [references\u002Fattractors-and-collision.md](references\u002Fattractors-and-collision.md) for full setup of each attractor and collision type.\n\n---\n\n## 8. Turbulence\n\nSet `turbulence_enabled = true` on `ParticleProcessMaterial` and tune `turbulence_noise_strength` (0.5–2.0 typical), `turbulence_noise_scale` (higher = larger, smoother swirls), `turbulence_noise_speed` (animate the noise field). Cheap effect for \"alive\" smoke, fire, dust.\n\n---\n\n## 9. Flipbook Animation (2D)\n\nSprite-sheet animated particles via `ParticleProcessMaterial.AnimSpeedMin\u002FMax` + `CanvasItemMaterial.ParticlesAnimHFrames\u002FVFrames` for the sheet layout. Particles cycle through frames over their lifetime.\n\n> See [references\u002Fflipbook-animation.md](references\u002Fflipbook-animation.md) for the full setup with GDScript + C# (v1.6.0 parity).\n\n---\n\n## 10. Performance and Common Pitfalls\n\nThe biggest wins are the obvious ones: keep `amount` at the minimum that reads well, keep `fixed_fps` at its default 30 for ambient systems (0 updates every frame), always set `visibility_rect` on 2D particles, and expose `amount_ratio` as a quality slider. Godot 4.7+ adds `request_particles_process()` for seeking a paused timeline.\n\nMost \"broken particles\" reports are one of eleven known causes — invisible (no texture \u002F no draw-pass mesh), vanishing (`lifetime` too short), one-shot not re-firing (`emitting = true` is ignored until the last burst's particles finish; `restart()` re-fires at once), wrong direction (2D Y is inverted), or a dark base `color`, which multiplies `color_ramp`.\n\nFull performance table, the 4.7+ timeline-seek API, dynamic quality scaling (GDScript + C#), and the complete symptom\u002Fcause\u002Ffix table: [references\u002Fperformance-and-pitfalls.md](references\u002Fperformance-and-pitfalls.md)\n\n---\n\n## 11. Implementation Checklist\n\n- [ ] Particle `amount` is set to the minimum needed for the visual effect\n- [ ] `lifetime` matches the visual duration — not too short or too long\n- [ ] `one_shot` is enabled for burst effects (explosions, impacts)\n- [ ] `preprocess` is set for always-visible ambient effects (fire, smoke, dust)\n- [ ] Emission shape matches the source geometry (sphere for explosions, box for area effects)\n- [ ] `color_ramp` fades alpha to 0 at the end so particles don't vanish abruptly\n- [ ] `scale_curve` shrinks particles over lifetime for natural fade\n- [ ] `local_coords` is set correctly — `true` for attached effects, `false` for world-space\n- [ ] One-shot particles are cleaned up with `queue_free` after `lifetime` + margin\n- [ ] `visibility_rect` (2D) is set to prevent particles from being culled prematurely\n- [ ] Dynamic quality scaling uses `amount_ratio` for player-accessible quality settings\n- [ ] Performance-heavy features (turbulence, trails) are disabled on low-end targets\n","# Particle Systems in Godot 4.3+\n\nAll examples target Godot 4.3+ with no deprecated APIs. GDScript is shown first, then C#.\n\n> **Related skills:** **shader-basics** for custom particle shaders, **3d-essentials** for lighting and environment that affect particles, **2d-essentials** for 2D rendering context, **tween-animation** for code-driven VFX timing, **godot-optimization** for particle performance tuning.\n\n---\n\n## 1. Core Concepts\n\n### GPU vs CPU Particles\n\n| Node                | Processing | Features                                | Use For                        |\n|---------------------|------------|-----------------------------------------|--------------------------------|\n| `GPUParticles2D`    | GPU        | Full features, high counts, trails      | Most 2D effects                |\n| `GPUParticles3D`    | GPU        | Full features, attractors, collision    | Most 3D effects                |\n| `CPUParticles2D`    | CPU        | Simpler, no trails\u002Fattractors           | Low-end devices, few particles |\n| `CPUParticles3D`    | CPU        | Simpler, no trails\u002Fattractors           | Low-end devices, few particles |\n\n**Rule of thumb:** Use GPU particles by default. Switch to CPU particles only for low-end\u002Fweb targets. Neither node exposes per-particle positions to scripts, so spawning objects at particle locations needs your own simulation.\n\n> You can convert between GPU and CPU particles in the editor: select the node → toolbar → **Convert to CPUParticles2D\u002F3D** (or vice versa).\n\n### Particle System Architecture\n\n```\nGPUParticles2D\u002F3D\n├── Process Material (ParticleProcessMaterial)   ← physics, emission, color\n├── Draw Pass 1 (Mesh)                            ← what each particle looks like\n└── (Optional) Draw Pass 2-4                      ← additional meshes\n```\n\n### Minimal Setup\n\n1. Add a **GPUParticles2D** (or 3D) node\n2. In Inspector → Process Material → **New ParticleProcessMaterial**\n3. Set **Amount** (number of particles)\n4. Configure emission, direction, velocity, gravity\n5. (2D) Set **Texture** for particle appearance\n6. (3D) Set **Draw Pass 1** mesh (QuadMesh for billboards, or custom mesh)\n\n---\n\n## 2. Key Node Properties\n\n### GPUParticles2D\u002F3D Properties\n\n| Property          | Type     | Description                                         |\n|-------------------|----------|-----------------------------------------------------|\n| `emitting`        | `bool`   | Start\u002Fstop emission                                 |\n| `amount`          | `int`    | Total particles alive at once                       |\n| `lifetime`        | `float`  | Seconds each particle lives                         |\n| `one_shot`        | `bool`   | Emit once then stop                                 |\n| `preprocess`      | `float`  | Simulate this many seconds before first frame       |\n| `speed_scale`     | `float`  | Time multiplier for particle physics                |\n| `explosiveness`   | `float`  | 0.0 = spread over lifetime, 1.0 = all at once      |\n| `fixed_fps`       | `int`    | Lock particle update rate (0 = match render FPS)    |\n| `local_coords`    | `bool`   | Particles move with the node (true) or stay in world (false) |\n| `draw_order`      | `enum`   | Index, Lifetime, or Reverse Lifetime                |\n| `amount_ratio`    | `float`  | Fraction of particles to emit (0.0–1.0)             |\n\n### One-Shot vs Continuous\n\n```gdscript\n# Continuous emitter (fire, smoke, ambient dust)\n$GPUParticles2D.one_shot = false\n$GPUParticles2D.emitting = true\n\n# One-shot burst (explosion, impact splash)\n$GPUParticles2D.one_shot = true\n$GPUParticles2D.emitting = false  # arm it\n# Later, trigger:\n$GPUParticles2D.restart()\n$GPUParticles2D.emitting = true\n```\n\n```csharp\n\u002F\u002F Continuous\nvar particles = GetNode\u003CGpuParticles2D>(\"GPUParticles2D\");\nparticles.OneShot = false;\nparticles.Emitting = true;\n\n\u002F\u002F One-shot burst\nparticles.OneShot = true;\nparticles.Emitting = false;\n\u002F\u002F Trigger:\nparticles.Restart();\nparticles.Emitting = true;\n```\n\n### Local Billboard Alignment (Godot 4.7+)\n\n`GPUParticles3D` gains `TRANSFORM_ALIGN_LOCAL_BILLBOARD` (`= 4`): each particle's Z axis faces the camera while preserving a given axis — X or Y, chosen via `transform_align_axis`. For billboarded particles, `transform_align_channel_filter` selects which custom channel to read to calculate their angle. `ParticleProcessMaterial` pairs this with per-axis rotation velocity: enable `use_rotation_velocity_3d`, then set `rotation_velocity_3d_min\u002Fmax` (`Vector3`, on the particle's local axes) and optionally `rotation_velocity_3d_curve` (per-axis curve over lifetime).\n\n```gdscript\n# 3D only — billboard toward the camera while keeping the Y axis fixed.\n# Assumes a ParticleProcessMaterial is assigned (section 1 setup).\n$GPUParticles3D.transform_align = GPUParticles3D.TRANSFORM_ALIGN_LOCAL_BILLBOARD\n$GPUParticles3D.transform_align_axis = RenderingServer.PARTICLES_ALIGN_AXIS_Y\n\nvar mat: ParticleProcessMaterial = $GPUParticles3D.process_material\nmat.use_rotation_velocity_3d = true\nmat.rotation_velocity_3d_min = Vector3(-2.0, 0.0, 0.0)\nmat.rotation_velocity_3d_max = Vector3(2.0, 0.0, 0.0)\n```\n\n```csharp\n\u002F\u002F Assumes a ParticleProcessMaterial is assigned (section 1 setup).\nvar particles = GetNode\u003CGpuParticles3D>(\"GPUParticles3D\");\nparticles.TransformAlign = GpuParticles3D.TransformAlignEnum.LocalBillboard;\nparticles.TransformAlignAxis = RenderingServer.ParticlesTransformAlignAxis.Y;\n\nvar mat = (ParticleProcessMaterial)particles.ProcessMaterial;\nmat.UseRotationVelocity3D = true;\nmat.RotationVelocity3DMin = new Vector3(-2.0f, 0.0f, 0.0f);\nmat.RotationVelocity3DMax = new Vector3(2.0f, 0.0f, 0.0f);\n```\n\n---\n\n## 3. ParticleProcessMaterial — Essential Properties\n\nThe material drives per-particle behavior: **emission shape** (Point \u002F Sphere \u002F Box \u002F Ring \u002F Points \u002F Directed Points), **direction + spread + initial velocity**, **gravity**, **scale and color over lifetime** (via `scale_curve` \u002F `color_ramp`), **damping**, **radial\u002Ftangential acceleration**, and **angular velocity**.\n\n> See [references\u002Fprocess-material-basics.md](references\u002Fprocess-material-basics.md) for the emission-shape table and GDScript + C# snippets for each property group.\n\n### Per-Axis 3D Scale & Rotation (Godot 4.7+)\n\nRandomize scale and initial orientation per axis instead of uniformly. `use_scale_3d` enables `scale_3d_min\u002Fmax` (`Vector3` random scale per particle); `use_rotation_3d` enables `rotation_3d_min\u002Fmax` (`Vector3`, degrees — works only in 3D).\n\n```gdscript\nmat.use_scale_3d = true\nmat.scale_3d_min = Vector3(0.5, 1.0, 0.5)\nmat.scale_3d_max = Vector3(1.0, 2.0, 1.0)\n\nmat.use_rotation_3d = true  # 3D only\nmat.rotation_3d_min = Vector3(0.0, -180.0, 0.0)  # degrees\nmat.rotation_3d_max = Vector3(0.0, 180.0, 0.0)\n```\n\n```csharp\nmat.UseScale3D = true;\nmat.Scale3DMin = new Vector3(0.5f, 1.0f, 0.5f);\nmat.Scale3DMax = new Vector3(1.0f, 2.0f, 1.0f);\n\nmat.UseRotation3D = true;  \u002F\u002F 3D only\nmat.Rotation3DMin = new Vector3(0.0f, -180.0f, 0.0f);  \u002F\u002F degrees\nmat.Rotation3DMax = new Vector3(0.0f, 180.0f, 0.0f);\n```\n\n### Inheriting Emitter Scale (Godot 4.7+)\n\n`particle_flag_inherit_emitter_scale` (default `false`): if `true`, particles inherit the scale of the emitter node. Has no effect when `local_coords` is `true`, since particles in local space are already affected by the emitter's scale.\n\n```gdscript\nmat.particle_flag_inherit_emitter_scale = true\n```\n\n```csharp\nmat.ParticleFlagInheritEmitterScale = true;\n```\n\n---\n\n## 4. Common VFX Recipes\n\nThe recipes most projects need: **fire** (2D, looped emission with hot-color gradient + scale-down), **explosion burst** (one-shot, high-amount short-lifetime), **dust \u002F footstep puff** (one-shot, scale-up + rapid fade).\n\n> See [references\u002Fvfx-recipes.md](references\u002Fvfx-recipes.md) for ready-to-use GDScript wiring and recommended `ParticleProcessMaterial` settings for all three.\n\n---\n\n## 5. Trails (Forward+ and Mobile only)\n\nSet `trail_enabled = true` on `GPUParticles2D\u002F3D` and assign a `Mesh` (`RibbonTrailMesh` or `TubeTrailMesh`). Trails are NOT supported in the Compatibility renderer.\n\n> See [references\u002Ftrails.md](references\u002Ftrails.md) for the setup and trail-mesh-type comparison.\n\n> **Godot 4.8+:** `Trail3D` (inherits `LineBase3D`) draws a flat line behind a moving object without particles, such as a sword swing or a projectile. Size it with `width` \u002F `width_curve`, and limit it by `lifetime` (default 0.2 s) or `max_length` through `limit_mode`; `mesh_alignment` picks a 3D line or a billboard. `color` \u002F `color_gradient` only show when the material uses vertex color as albedo.\n\n---\n\n## 6. Subemitters\n\nA particle can make another particle system emit at a constant rate, at collision, at its death, or (Godot 4.4+) at its birth. Configure via `ParticleProcessMaterial.sub_emitter_mode` + the `sub_emitter` property on the parent particles node.\n\n> See [references\u002Fsubemitters.md](references\u002Fsubemitters.md) for trigger modes, scene setup, GDScript and C# (v1.6.0 parity), and limitations.\n\n> **Note:** With `sub_emitter_keep_velocity = true` (default `false`), subemitted particles inherit the parent particle's velocity when they spawn. This is unchanged in 4.7: a regression in 4.7 dev builds that broke the inheritance was fixed before 4.7 stable ([GH-118062](https:\u002F\u002Fgithub.com\u002Fgodotengine\u002Fgodot\u002Fpull\u002F118062)), so nothing needs migrating from 4.6.\n\n---\n\n## 7. Attractors & Collision (3D)\n\n`GPUParticlesAttractor*3D` (Box \u002F Sphere \u002F Vector Field) pulls particles toward a region. `GPUParticlesCollision*3D` (Box \u002F Sphere \u002F SDF \u002F HeightField) lets particles bounce off geometry. Compatibility runs box\u002Fsphere attractors and box\u002Fsphere\u002Fheight-field colliders; vector-field attractors and SDF colliders need Forward+ or Mobile. 2D has no attractor nodes, but `GPUParticles2D` collide with `LightOccluder2D` nodes when `collision_mode` is set.\n\n> See [references\u002Fattractors-and-collision.md](references\u002Fattractors-and-collision.md) for full setup of each attractor and collision type.\n\n---\n\n## 8. Turbulence\n\nSet `turbulence_enabled = true` on `ParticleProcessMaterial` and tune `turbulence_noise_strength` (0.5–2.0 typical), `turbulence_noise_scale` (higher = larger, smoother swirls), `turbulence_noise_speed` (animate the noise field). Cheap effect for \"alive\" smoke, fire, dust.\n\n---\n\n## 9. Flipbook Animation (2D)\n\nSprite-sheet animated particles via `ParticleProcessMaterial.AnimSpeedMin\u002FMax` + `CanvasItemMaterial.ParticlesAnimHFrames\u002FVFrames` for the sheet layout. Particles cycle through frames over their lifetime.\n\n> See [references\u002Fflipbook-animation.md](references\u002Fflipbook-animation.md) for the full setup with GDScript + C# (v1.6.0 parity).\n\n---\n\n## 10. Performance and Common Pitfalls\n\nThe biggest wins are the obvious ones: keep `amount` at the minimum that reads well, keep `fixed_fps` at its default 30 for ambient systems (0 updates every frame), always set `visibility_rect` on 2D particles, and expose `amount_ratio` as a quality slider. Godot 4.7+ adds `request_particles_process()` for seeking a paused timeline.\n\nMost \"broken particles\" reports are one of eleven known causes — invisible (no texture \u002F no draw-pass mesh), vanishing (`lifetime` too short), one-shot not re-firing (`emitting = true` is ignored until the last burst's particles finish; `restart()` re-fires at once), wrong direction (2D Y is inverted), or a dark base `color`, which multiplies `color_ramp`.\n\nFull performance table, the 4.7+ timeline-seek API, dynamic quality scaling (GDScript + C#), and the complete symptom\u002Fcause\u002Ffix table: [references\u002Fperformance-and-pitfalls.md](references\u002Fperformance-and-pitfalls.md)\n\n---\n\n## 11. Implementation Checklist\n\n- [ ] Particle `amount` is set to the minimum needed for the visual effect\n- [ ] `lifetime` matches the visual duration — not too short or too long\n- [ ] `one_shot` is enabled for burst effects (explosions, impacts)\n- [ ] `preprocess` is set for always-visible ambient effects (fire, smoke, dust)\n- [ ] Emission shape matches the source geometry (sphere for explosions, box for area effects)\n- [ ] `color_ramp` fades alpha to 0 at the end so particles don't vanish abruptly\n- [ ] `scale_curve` shrinks particles over lifetime for natural fade\n- [ ] `local_coords` is set correctly — `true` for attached effects, `false` for world-space\n- [ ] One-shot particles are cleaned up with `queue_free` after `lifetime` + margin\n- [ ] `visibility_rect` (2D) is set to prevent particles from being culled prematurely\n- [ ] Dynamic quality scaling uses `amount_ratio` for player-accessible quality settings\n- [ ] Performance-heavy features (turbulence, trails) are disabled on low-end targets\n",{"name":5,"description":7},"master","60c28fdc40706a24576731e9fb3508b9c95258ad","skills\u002Fparticles-vfx",63,"https:\u002F\u002Fgithub.com\u002Fjame581\u002FGodotPrompter","https:\u002F\u002Fgithub.com\u002Fjame581","https:\u002F\u002Fjanmesarc.online\u002F","Software engineer. My biggest passion is game development.","2026-11-13 02:28:46",{"source":8,"skillName":5,"commands":45,"prompt":55,"zipAvailable":56},[46,49,52],{"tool":47,"command":48},"npx","npx skills add jame581\u002FGodotPrompter --skill particles-vfx",{"tool":50,"command":51},"bunx","bunx skills add jame581\u002FGodotPrompter --skill particles-vfx",{"tool":53,"command":54},"pnpm","pnpm dlx skills add jame581\u002FGodotPrompter --skill particles-vfx","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fjame581\u002FGodotPrompter\u002Fblob\u002Fmaster\u002Fskills\u002Fparticles-vfx\u002FSKILL.md",true,[58,64,68,72,76,80,84],{"path":59,"resourceType":60,"resourceTypeDesc":61,"sizeBytes":62,"sourceHtmlUrl":63},"references\u002Fattractors-and-collision.md","REFERENCE","参考文档",3484,"https:\u002F\u002Fgithub.com\u002Fjame581\u002FGodotPrompter\u002Fblob\u002Fmaster\u002Fskills\u002Fparticles-vfx\u002Freferences\u002Fattractors-and-collision.md",{"path":65,"resourceType":60,"resourceTypeDesc":61,"sizeBytes":66,"sourceHtmlUrl":67},"references\u002Fflipbook-animation.md",1781,"https:\u002F\u002Fgithub.com\u002Fjame581\u002FGodotPrompter\u002Fblob\u002Fmaster\u002Fskills\u002Fparticles-vfx\u002Freferences\u002Fflipbook-animation.md",{"path":69,"resourceType":60,"resourceTypeDesc":61,"sizeBytes":70,"sourceHtmlUrl":71},"references\u002Fperformance-and-pitfalls.md",4817,"https:\u002F\u002Fgithub.com\u002Fjame581\u002FGodotPrompter\u002Fblob\u002Fmaster\u002Fskills\u002Fparticles-vfx\u002Freferences\u002Fperformance-and-pitfalls.md",{"path":73,"resourceType":60,"resourceTypeDesc":61,"sizeBytes":74,"sourceHtmlUrl":75},"references\u002Fprocess-material-basics.md",3708,"https:\u002F\u002Fgithub.com\u002Fjame581\u002FGodotPrompter\u002Fblob\u002Fmaster\u002Fskills\u002Fparticles-vfx\u002Freferences\u002Fprocess-material-basics.md",{"path":77,"resourceType":60,"resourceTypeDesc":61,"sizeBytes":78,"sourceHtmlUrl":79},"references\u002Fsubemitters.md",2822,"https:\u002F\u002Fgithub.com\u002Fjame581\u002FGodotPrompter\u002Fblob\u002Fmaster\u002Fskills\u002Fparticles-vfx\u002Freferences\u002Fsubemitters.md",{"path":81,"resourceType":60,"resourceTypeDesc":61,"sizeBytes":82,"sourceHtmlUrl":83},"references\u002Ftrails.md",2007,"https:\u002F\u002Fgithub.com\u002Fjame581\u002FGodotPrompter\u002Fblob\u002Fmaster\u002Fskills\u002Fparticles-vfx\u002Freferences\u002Ftrails.md",{"path":85,"resourceType":60,"resourceTypeDesc":61,"sizeBytes":86,"sourceHtmlUrl":87},"references\u002Fvfx-recipes.md",4803,"https:\u002F\u002Fgithub.com\u002Fjame581\u002FGodotPrompter\u002Fblob\u002Fmaster\u002Fskills\u002Fparticles-vfx\u002Freferences\u002Fvfx-recipes.md",[89,109,130,160,184,199],{"skillNo":90,"name":91,"nameZh":6,"description":92,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":93,"categories":94,"keywords":95,"publishedAt":30},"01M6KRFE5BR2PSD08ZKDAS66R7","xr-development","Use when building VR\u002FAR\u002FXR applications — OpenXR setup, XROrigin3D, hand tracking, controllers, passthrough, and Meta Quest deployment in Godot 4.3+","https:\u002F\u002Fgithub.com\u002Fjame581\u002FGodotPrompter\u002Fblob\u002Fmaster\u002Fskills\u002Fxr-development\u002FSKILL.md",[],[96,97,29,98,99,100,101,102,103,104,105,24,106,107,108],"xr development","development","deployment","godot","vr","setup","tracking","godot 4","ar","hand","Meta","applications","quest",{"skillNo":110,"name":111,"nameZh":6,"description":112,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":113,"categories":114,"keywords":115,"publishedAt":30},"01M6KRF8GZTG1TAS506MFBSGFC","web-services","Use when a Godot game calls a web server — HTTPRequest, downloads, REST\u002FJSON APIs, auth headers, WebSocketPeer clients, TLS, retries, and keeping secrets out of the build. Not for game networking\u002FRPCs (multiplayer-basics) or browser export (web-export)","https:\u002F\u002Fgithub.com\u002Fjame581\u002FGodotPrompter\u002Fblob\u002Fmaster\u002Fskills\u002Fweb-services\u002FSKILL.md",[],[116,117,118,119,120,121,122,123,24,29,99,124,125,126,127,128,129],"web services","web","services","tls","retries","calling","auth","downloads","clients","headers","secrets","json","build","REST",{"skillNo":131,"name":132,"nameZh":6,"description":133,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":134,"categories":135,"keywords":141,"publishedAt":30},"01M6KRF38Q4WSKAYFS56PG87T0","web-export","Use when shipping a Godot game to the browser — Web export preset options, threads vs no-threads and COOP\u002FCOEP headers, hosting on itch.io or your own server, PWA, JavaScriptBridge, user:\u002F\u002F persistence, audio and input limits, and load size","https:\u002F\u002Fgithub.com\u002Fjame581\u002FGodotPrompter\u002Fblob\u002Fmaster\u002Fskills\u002Fweb-export\u002FSKILL.md",[136],{"categoryNo":137,"categoryName":138,"taxonomyType":139,"taxonomyTypeDesc":140},"01JBSEEDCAT000000000000016","图像与多媒体","SCENARIO","使用场景",[117,142,143,144,145,146,147,148,125,149,150,29,151,152,153,154,155,156,24,157,158,159],"export","web export","threads","limits","shipping","size","options","hosting","input","Coop","preset","browser","game","io","load","pwa","Audio","server",{"skillNo":161,"name":162,"nameZh":6,"description":163,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":164,"categories":165,"keywords":174,"publishedAt":30},"01M6KREYFETEBH62ZTN6EZH2X3","using-godot-prompter","Bootstrap skill — establishes how to find and use GodotPrompter skills, with platform-specific tool mapping","https:\u002F\u002Fgithub.com\u002Fjame581\u002FGodotPrompter\u002Fblob\u002Fmaster\u002Fskills\u002Fusing-godot-prompter\u002FSKILL.md",[166,169],{"categoryNo":167,"categoryName":168,"taxonomyType":139,"taxonomyTypeDesc":140},"01JBSEEDCAT000000000000023","Skill与智能体开发",{"categoryNo":170,"categoryName":171,"taxonomyType":172,"taxonomyTypeDesc":173},"01JBSEEDCAT000000000000032","设计师","PROFESSION","适用职业",[99,175,176,177,178,24,179,180,181,182,183],"using godot prompter","find","with","bootstrap","tool","platform","mapping","how","how to",{"skillNo":185,"name":186,"nameZh":6,"description":187,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":188,"categories":189,"keywords":190,"publishedAt":30},"01M6KRER5G7EQWKGAFN8QJKQ69","tween-animation","Use when implementing tweens — property animation, method tweening, chaining, parallel sequences, easing, and common UI\u002Fgameplay motion recipes","https:\u002F\u002Fgithub.com\u002Fjame581\u002FGodotPrompter\u002Fblob\u002Fmaster\u002Fskills\u002Ftween-animation\u002FSKILL.md",[],[191,192,24,193,194,195,196,197,28,26,23,29,198],"tween animation","Animation","motion","parallel","gameplay","chaining","ui","sequences",{"skillNo":200,"name":201,"nameZh":6,"description":202,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":203,"categories":204,"keywords":205,"publishedAt":30},"01M6KREKGCQMVDV8WX7HWX8BZG","state-machine","Use when building a state machine or refactoring logic into one — enum, node, and resource-based FSM patterns with trade-offs. Not for adding states to an existing one","https:\u002F\u002Fgithub.com\u002Fjame581\u002FGodotPrompter\u002Fblob\u002Fmaster\u002Fskills\u002Fstate-machine\u002FSKILL.md",[],[206,207,208,99,29,209,210,211,212,213,177,24,23,214],"state","state machine","machine","patterns","node","fsm","state machines","trade","trade-offs"]