using UnityEngine; [DisallowMultipleComponent] public class CoinVFXAdder : MonoBehaviour { [Header("VFX Prefab (one-shot)")] public ParticleSystem vfxPrefab; [Header("Spawn Options")] public Vector3 spawnOffsetLocal; // offset in source local space public bool inheritRotation = false; // use source.rotation public Transform parentOverride; // null = world [Header("Lifetime")] public bool autoDestroyIfNeeded = true; public float extraLifetime = 0.25f; /// Spawn at this component's transform (still supported). public void SpawnVFX() { SpawnAt(transform); } /// Spawn at a specific source (e.g., the coin), so this can sit on an ancestor. public void SpawnAt(Transform source) { if (!vfxPrefab || !source) return; Vector3 pos = source.TransformPoint(spawnOffsetLocal); Quaternion rot = inheritRotation ? source.rotation : Quaternion.identity; Transform parent = parentOverride ? parentOverride : null; var ps = Instantiate(vfxPrefab, pos, rot, parent); ps.Play(true); if (ps.main.stopAction == ParticleSystemStopAction.Destroy) return; if (autoDestroyIfNeeded) { Destroy(ps.gameObject, EstimateLifetime(ps) + extraLifetime); } } private static float EstimateLifetime(ParticleSystem ps) { var main = ps.main; float dur = main.duration; float lt = 0f; var c = main.startLifetime; switch (c.mode) { case ParticleSystemCurveMode.Constant: lt = c.constant; break; case ParticleSystemCurveMode.TwoConstants: lt = Mathf.Max(c.constantMin, c.constantMax); break; case ParticleSystemCurveMode.Curve: if (c.curve != null && c.curve.length > 0) lt = c.curve.keys[^1].time; break; case ParticleSystemCurveMode.TwoCurves: float a = (c.curveMin != null && c.curveMin.length > 0) ? c.curveMin.keys[^1].time : 0f; float b = (c.curveMax != null && c.curveMax.length > 0) ? c.curveMax.keys[^1].time : 0f; lt = Mathf.Max(a, b); break; } return dur + lt; } }