using UnityEngine; namespace TKS { /// /// 이펙트 자연 소멸(2026-11-10 PD 「슬링샷 이동이 종료될 때 자연스럽게 소멸」): 방출을 멈추고 살아 있는 입자의 불투명도를 dur 초 동안 0 으로 낮춘 뒤 지운다. /// 수명이 무한인 층(투사체 머리·꼬리)도 사라지게 입자 색 알파를 직접 줄인다(모든 이식 셰이더가 입자 색 알파를 곱함). 값 = 표 skill_vfx.csv f_fade. /// public class SkillVfxFade : MonoBehaviour { float dur; float t; ParticleSystem[] systems; ParticleSystem.Particle[] buf = new ParticleSystem.Particle[64]; /// 2D 평면 이펙트(b_flat)의 스프라이트 층 — 처음 불투명도에서 0 으로(트레일은 방출만 멈추면 제 길이만큼 줄어듦). SpriteRenderer[] sprites; float[] spriteAlpha; /// 꼬리(트레일) — 남은 꼬리 전체의 불투명도를 함께 낮춤(IB 속도 꼬리 0.6초가 멈춘 뒤 늦게 사라지던 문제 · PD 2026-11-10). TrailRenderer[] trails; Gradient[] trailGrad; public static void Begin(GameObject go, float seconds) { if (go == null) return; var f = go.GetComponent(); if (f != null) return; f = go.AddComponent(); f.dur = Mathf.Max(0.05f, seconds); f.systems = go.GetComponentsInChildren(true); foreach (var ps in f.systems) ps.Stop(false, ParticleSystemStopBehavior.StopEmitting); f.trails = go.GetComponentsInChildren(true); f.trailGrad = new Gradient[f.trails.Length]; for (int i = 0; i < f.trails.Length; i++) { f.trails[i].emitting = false; f.trailGrad[i] = f.trails[i].colorGradient; } f.sprites = go.GetComponentsInChildren(true); f.spriteAlpha = new float[f.sprites.Length]; for (int i = 0; i < f.sprites.Length; i++) f.spriteAlpha[i] = f.sprites[i].color.a; } void LateUpdate() { float prev = Mathf.Clamp01(1f - t / dur); t += Time.deltaTime; float now = Mathf.Clamp01(1f - t / dur); float k = prev > 1e-4f ? now / prev : 0f; // 이번 프레임 알파 배율(누적하면 1 - t/dur) foreach (var ps in systems) { if (ps == null) continue; int n = ps.particleCount; if (n == 0) continue; if (buf.Length < n) buf = new ParticleSystem.Particle[Mathf.NextPowerOfTwo(n)]; n = ps.GetParticles(buf, n); for (int i = 0; i < n; i++) { var c = buf[i].startColor; c.a = (byte)Mathf.Clamp(Mathf.RoundToInt(c.a * k), 0, 255); buf[i].startColor = c; } ps.SetParticles(buf, n); } for (int i = 0; i < trails.Length; i++) { if (trails[i] == null) continue; var g = trailGrad[i]; var ak = g.alphaKeys; for (int j = 0; j < ak.Length; j++) ak[j].alpha *= now; var ng = new Gradient(); ng.SetKeys(g.colorKeys, ak); ng.mode = g.mode; trails[i].colorGradient = ng; } for (int i = 0; i < sprites.Length; i++) { if (sprites[i] == null) continue; var c = sprites[i].color; c.a = spriteAlpha[i] * now; sprites[i].color = c; } if (t >= dur) Destroy(gameObject); } } }