From c6644a213263375c7a35b5082ef4b71cc58964e6 Mon Sep 17 00:00:00 2001 From: mob-sakai Date: Thu, 9 Jun 2022 01:47:42 +0900 Subject: [PATCH] fix: correct world space particle position when changing screen size --- Scripts/UIParticleRenderer.cs | 45 +++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/Scripts/UIParticleRenderer.cs b/Scripts/UIParticleRenderer.cs index e97fe41..25ca2eb 100644 --- a/Scripts/UIParticleRenderer.cs +++ b/Scripts/UIParticleRenderer.cs @@ -26,6 +26,7 @@ namespace Coffee.UIExtensions private Material _modifiedMaterial; private Vector3 _prevScale; private Vector3 _prevPsPos; + private Vector2Int _prevScreenSize; private bool _delay = false; private bool _prewarm = false; @@ -144,6 +145,7 @@ namespace Coffee.UIExtensions _prevScale = GetWorldScale(); _prevPsPos = _particleSystem.transform.position; + _prevScreenSize = new Vector2Int(Screen.width, Screen.height); _delay = true; canvasRenderer.SetTexture(null); @@ -188,8 +190,14 @@ namespace Coffee.UIExtensions else #endif { + ResolveResolutionChange(psPos, scale); Simulate(scale, _parent.isPaused || _delay); + if (_delay && !_parent.isPaused) + { + Simulate(scale, _parent.isPaused); + } + // When the ParticleSystem simulation is complete, stop it. if (!main.loop && main.duration <= _particleSystem.time && (_particleSystem.IsAlive() || _particleSystem.particleCount == 0)) { @@ -320,6 +328,43 @@ namespace Coffee.UIExtensions } } + /// + /// For world simulation, interpolate particle positions when the screen size is changed. + /// + /// + /// + private void ResolveResolutionChange(Vector3 psPos, Vector3 scale) + { + var screenSize = new Vector2Int(Screen.width, Screen.height); + if ((_prevScreenSize != screenSize || _prevScale != scale) && _particleSystem.main.simulationSpace == ParticleSystemSimulationSpace.World && _parent.uiScaling) + { + // Update particle array size and get particles. + var size = _particleSystem.particleCount; + if (s_Particles.Length < size) + { + s_Particles = new ParticleSystem.Particle[Mathf.NextPowerOfTwo(size)]; + } + _particleSystem.GetParticles(s_Particles, size); + + // Resolusion resolver: + // (psPos / scale) / (prevPsPos / prevScale) -> psPos * scale.inv * prevPsPos.inv * prevScale + var modifier = psPos.GetScaled(scale.Inverse(), _prevPsPos.Inverse(), _prevScale); + for (var i = 0; i < size; i++) + { + var particle = s_Particles[i]; + particle.position = particle.position.GetScaled(modifier); + s_Particles[i] = particle; + } + _particleSystem.SetParticles(s_Particles, size); + + // Delay: Do not progress in the frame where the resolution has been changed. + _delay = true; + _prevScale = scale; + _prevPsPos = psPos; + } + _prevScreenSize = screenSize; + } + private void Simulate(Vector3 scale, bool paused) { var main = _particleSystem.main;