From 7f22269c27ec76964f0c2cb406e5e8b5d53f14b5 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 3 Oct 2026 17:50:28 +0000 Subject: [PATCH] [Reviewed] [3D particle emitter] Fix the emission zone radius and relative particles with the 3D renderer world scale The emitter transformation (which includes the scale of the layer, i.e. the 3D renderer world scale) already converts the emitter shape, and the velocities of relative particles, to the Three.js world units: - The emission zone radius was converted twice: zones were 100 times too small. - The start speed and the gravity are now converted only for particles in world space: relative particles were 100 times too slow. - The trail length is a number of positions, not a distance: it is no longer converted (trails were almost invisible). - The emitter world matrix is updated with its parents when created, so that the first particles are emitted with the layer scale. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01HdyuCYDD8w7U2Q3p1aHY5M --- extensions/reviewed/ParticleEmitter3D.json | 46 ++++++++++++++++++---- 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/extensions/reviewed/ParticleEmitter3D.json b/extensions/reviewed/ParticleEmitter3D.json index 8514bafdd..2b5f7f904 100644 --- a/extensions/reviewed/ParticleEmitter3D.json +++ b/extensions/reviewed/ParticleEmitter3D.json @@ -10,7 +10,7 @@ "name": "ParticleEmitter3D", "previewIconUrl": "https://asset-resources.gdevelop.io/public-resources/Icons/f2e5a34bf465f781866677762d385d6c8e9e8d203383f2df9a3b7e0fad6a2cb5_fire.svg", "shortDescription": "Display a large number of particles in 3D to create visual effects in a 3D game.", - "version": "3.2.0", + "version": "3.2.1", "description": [ "3D particle emitters let you create and display many small particles to simulate visual effects in your game — like fire, explosions, smoke, dust, magic, rain or snow.", "", @@ -254,6 +254,9 @@ " this.particleSystem = particleSystem;", " this.sprayConeAngle = 0;", " this.zoneRadius = 0;", + " this.startSpeedMin = 0;", + " this.startSpeedMax = 0;", + " this.gravity = 0;", " this.colorOverLife = colorOverLife;", " this.sizeOverLife = sizeOverLife;", " this.applyForce = applyForce;", @@ -283,7 +286,7 @@ " if (!startLength) {", " return;", " }", - " startLength.a = startLengthMin * this.inverseWorldScale;", + " startLength.a = startLengthMin;", " }", "", " /**", @@ -294,7 +297,7 @@ " if (!startLength) {", " return;", " }", - " startLength.b = startLengthMax * this.inverseWorldScale;", + " startLength.b = startLengthMax;", " }", "", " /**", @@ -385,14 +388,31 @@ " * @param startSpeedMin {number}", " */", " setStartSpeedMin(startSpeedMin) {", - " this.particleSystem.startSpeed.a = startSpeedMin * this.inverseWorldScale;", + " this.startSpeedMin = startSpeedMin;", + " this.updateStartSpeed();", " }", "", " /**", " * @param startSpeedMax {number}", " */", " setStartSpeedMax(startSpeedMax) {", - " this.particleSystem.startSpeed.b = startSpeedMax * this.inverseWorldScale;", + " this.startSpeedMax = startSpeedMax;", + " this.updateStartSpeed();", + " }", + "", + " /**", + " * Velocities of particles in world space are in the Three.js world units,", + " * so they need the world scale. Velocities of relative particles are in", + " * the emitter units, converted by the emitter transformation.", + " */", + " getVelocityScale() {", + " return this.particleSystem.worldSpace ? this.inverseWorldScale : 1;", + " }", + "", + " updateStartSpeed() {", + " const velocityScale = this.getVelocityScale();", + " this.particleSystem.startSpeed.a = this.startSpeedMin * velocityScale;", + " this.particleSystem.startSpeed.b = this.startSpeedMax * velocityScale;", " }", "", " /**", @@ -421,6 +441,8 @@ " */", " setParticlesRelative(areParticlesRelative) {", " this.particleSystem.worldSpace = !areParticlesRelative;", + " this.updateStartSpeed();", + " this.updateGravity();", " }", "", " /**", @@ -440,7 +462,8 @@ " }", "", " updateEmitterShape() {", - " const zoneRadius = Math.max(0, this.zoneRadius) * this.inverseWorldScale;", + " // The emitter transformation converts the shape to the Three.js world units.", + " const zoneRadius = Math.max(0, this.zoneRadius);", " // Without a zone, a spray angle of 0 emits in every direction from a point.", " // With a zone, it emits straight from every point of the disc.", " const isCone = this.sprayConeAngle <= 180 && (0 < this.sprayConeAngle || 0 < zoneRadius);", @@ -475,7 +498,12 @@ " * @param gravity {number}", " */", " setGravity(gravity) {", - " this.applyForce.magnitude.value = gravity * this.inverseWorldScale;", + " this.gravity = gravity;", + " this.updateGravity();", + " }", + "", + " updateGravity() {", + " this.applyForce.magnitude.value = this.gravity * this.getVelocityScale();", " }", "", " /**", @@ -7242,7 +7270,9 @@ " layer.getRenderer().add3DRendererObject(particleSystem.emitter);", "}", "", - "particleSystem.emitter.updateMatrixWorld(true);", + "// Update the parents too, so that the first particles are emitted with the", + "// scale of the layer (the 3D renderer world scale).", + "particleSystem.emitter.updateWorldMatrix(true, true);", "", "", "// See doStepPostEvents",