// Assets/_Project/Scripts/VFX/CoinBurstVfx.cs using UnityEngine; namespace TD.VFX { /// /// Self-contained, code-configured gold-coin burst used as the zero-art placeholder for the /// tower-sell effect. Configures its own for a short radial /// spray of gold specks thrown up in random arcs under gravity, then destroys itself. /// /// /// Instantiated at runtime by when no authored VFX prefab is /// assigned. It can also be dropped on a prefab in the editor and tuned. Replace with an /// authored particle / VFX-graph prefab (assigned on the spawner) when art is ready — nothing /// else needs to change. /// [RequireComponent(typeof(ParticleSystem))] public class CoinBurstVfx : MonoBehaviour { [Tooltip("How many coin specks to throw.")] [SerializeField] private int coinCount = 14; [Tooltip("Longest a speck lives (seconds). The whole effect self-destructs shortly after.")] [SerializeField] private float lifetime = 0.6f; [Tooltip("Gold tint applied to the specks.")] [SerializeField] private Color coinColor = new Color(1f, 0.84f, 0.2f, 1f); private void Awake() { var ps = GetComponent(); if (ps == null) ps = gameObject.AddComponent(); Configure(ps); } private void Configure(ParticleSystem ps) { // Reconfiguring modules requires the system to be stopped first. ps.Stop(true, ParticleSystemStopBehavior.StopEmittingAndClear); var main = ps.main; main.duration = 0.1f; main.loop = false; main.playOnAwake = false; main.startLifetime = new ParticleSystem.MinMaxCurve(lifetime * 0.6f, lifetime); main.startSpeed = new ParticleSystem.MinMaxCurve(2.5f, 5f); main.startSize = new ParticleSystem.MinMaxCurve(0.07f, 0.16f); main.startRotation = new ParticleSystem.MinMaxCurve(0f, Mathf.PI * 2f); main.startColor = coinColor; main.gravityModifier = 2.5f; // arc up then fall back down quickly main.simulationSpace = ParticleSystemSimulationSpace.World; main.maxParticles = 64; main.stopAction = ParticleSystemStopAction.None; var emission = ps.emission; emission.enabled = true; emission.rateOverTime = 0f; // burst only, no continuous stream emission.SetBursts(new[] { new ParticleSystem.Burst(0f, (short)coinCount) }); // Hemisphere pointing up → specks spray outward and upward in random directions. var shape = ps.shape; shape.enabled = true; shape.shapeType = ParticleSystemShapeType.Hemisphere; shape.radius = 0.12f; // Fade the specks out over the back half of their life so they "decay quickly". var col = ps.colorOverLifetime; col.enabled = true; var grad = new Gradient(); grad.SetKeys( new[] { new GradientColorKey(coinColor, 0f), new GradientColorKey(coinColor, 1f) }, new[] { new GradientAlphaKey(1f, 0f), new GradientAlphaKey(1f, 0.55f), new GradientAlphaKey(0f, 1f), }); col.color = new ParticleSystem.MinMaxGradient(grad); // Give the specks a visible, transparent-capable material even with no assigned art. var renderer = GetComponent(); if (renderer != null) { renderer.renderMode = ParticleSystemRenderMode.Billboard; if (renderer.sharedMaterial == null) { Shader shader = Shader.Find("Universal Render Pipeline/Particles/Unlit") ?? Shader.Find("Sprites/Default") ?? Shader.Find("Legacy Shaders/Particles/Alpha Blended Premultiply"); if (shader != null) renderer.material = new Material(shader) { color = coinColor }; } } ps.Play(); // Tear down after the last speck has died (plus a small margin). Destroy(gameObject, lifetime + 0.25f); } } }