Unity粒子金币收集系统:单粒子重复收集问题求助
问题分析与解决方案
问题核心:同一金币粒子被重复触发Enter事件,导致单粒子多次计入金币计数。原因是设置粒子remainingLifetime = 0后,粒子不会立即被销毁,需等到粒子系统下一次更新才会移除,期间粒子若仍处于玩家碰撞体内,会被重复检测为进入事件。
修复步骤
1. 配置粒子系统自定义数据
选中金币粒子预制体的ParticleSystem组件,添加Custom Data模块:
- 启用
Float通道(选择Element 0) - 设置初始值为
0(代表未收集状态)
2. 修改CoinParticle脚本
更新OnParticleTrigger方法,通过自定义数据标记已收集的粒子,避免重复计数:
private void OnParticleTrigger() { int triggeredParticles = ps.GetTriggerParticles(ParticleSystemTriggerEventType.Enter, particles); for (int i = 0; i < triggeredParticles; i++) { ParticleSystem.Particle p = particles[i]; // 检查粒子是否已被收集 float isCollected = p.GetCustomData(0); if (isCollected >= 1f) { continue; } p.remainingLifetime = 0f; p.SetCustomData(0, 1f); // 标记为已收集 controller.goldAmount++; particles[i] = p; } ps.SetTriggerParticles(ParticleSystemTriggerEventType.Enter, particles); }
3. 额外优化(可选)
- 避免在
Awake中使用FindAnyObjectByType,改为通过Inspector面板直接赋值玩家引用,减少性能开销 - 添加自动销毁逻辑,粒子全部消失后销毁金币粒子对象:
private IEnumerator DestroyAfterParticles() { yield return new WaitUntil(() => !ps.isPlaying && ps.particleCount == 0); Destroy(gameObject); } public void dropCoins(Vector2Int coinDropRange) { ParticleSystem.Burst burst = new ParticleSystem.Burst(0.0f, (short)coinDropRange.x, (short)coinDropRange.y, 0.01f); ps.emission.SetBursts(new ParticleSystem.Burst[] { burst }); ps.Play(); StartCoroutine(DestroyAfterParticles()); }
4. 检查粒子系统Trigger设置
- 仅勾选
Enter事件,取消Stay/Exit的勾选(除非有特殊需求) - 确认触发碰撞体绑定的是玩家的主碰撞体(如胶囊碰撞体),而非子对象的冗余碰撞体
内容的提问来源于stack exchange,提问作者TheDemonDonut
相关产品推荐
相关产品推荐

