Unity技术问询:如何在OnParticleTrigger中获取碰撞Collider实现粒子击中扣血
解决Unity粒子系统OnParticleTrigger获取碰撞Collider的问题
嘿,我刚好做过类似的粒子触发伤害的功能,来帮你搞定这个问题!你现在的核心问题是OnParticleTrigger()方法不像普通的OnTriggerEnter那样直接给你other参数,得通过Unity ParticleSystem的专用API来获取碰撞到的Collider,同时还能满足你“粒子碰撞后继续飞行”“不重复伤害同一目标”的需求。
第一步:先确保粒子系统的Trigger模块配置正确
在你的粒子系统Inspector面板里,先完成这些设置:
- 启用Trigger模块
- 在
Triggered Events里勾选Enter(我们要在粒子刚接触目标时触发伤害) - 在
Colliders区域,添加你希望粒子检测碰撞的敌方所在的Layer(或者直接拖入特定碰撞体,用层更灵活) - 把
Interaction设置为Collide with World(这样粒子能和非Trigger的Collider交互,同时碰撞后不会消失,满足你继续飞行的需求)
第二步:修改你的脚本代码
下面是完整的修正代码,我会加上详细注释:
using UnityEngine; using System.Collections.Generic; public class ParticleDamageHandler : MonoBehaviour { // 存储已经造成过伤害的对象,避免重复伤害 private HashSet<GameObject> hitObjects = new HashSet<GameObject>(); // 用于临时存储触发的粒子(ParticleSystem API要求用List) private List<ParticleSystem.Particle> triggeredParticles = new List<ParticleSystem.Particle>(); // 用于临时存储碰撞到的Collider private List<Collider> hitColliders = new List<Collider>(); private ParticleSystem _particleSystem; void Awake() { // 获取当前对象上的ParticleSystem组件 _particleSystem = GetComponent<ParticleSystem>(); } private void OnParticleTrigger() { // 获取所有触发了Enter事件的粒子和对应的碰撞体 int particleCount = _particleSystem.GetTriggerParticles(ParticleSystemTriggerEventType.Enter, triggeredParticles, hitColliders); // 遍历每个碰撞到的Collider for (int i = 0; i < particleCount; i++) { Collider hitCollider = hitColliders[i]; GameObject hitObj = hitCollider.gameObject; // 检查这个对象有没有被伤害过,并且实现了IDamageable接口 if (!hitObjects.Contains(hitObj) && hitObj.TryGetComponent(out IDamageable damageable)) { // 造成伤害 damageable.GetDamage(PlayerScript.instance.damage); // 添加到已伤害列表 hitObjects.Add(hitObj); } } // 必须调用这个方法来重置粒子系统的触发状态,否则会一直重复触发 _particleSystem.SetTriggerParticles(ParticleSystemTriggerEventType.Enter, triggeredParticles); } }
关键细节解释
为什么用HashSet而不是List存hitObjects?
HashSet的Contains方法查找效率比List高,尤其是当你有很多敌方单位时,性能更好。当然如果你的场景敌人不多,用List也没问题。GetTriggerParticles和SetTriggerParticles的作用
ParticleSystem的触发事件是批量处理的,GetTriggerParticles会把当前帧所有触发指定事件(这里是Enter)的粒子和碰撞体取出来,处理完后必须用SetTriggerParticles把粒子状态回传给系统,否则会出现重复触发的问题。空安全判断
用TryGetComponent代替直接GetComponent,可以避免当敌方对象没有实现IDamageable接口时报空引用错误,让代码更健壮。粒子继续飞行的保障
只要你在Trigger模块里没有勾选Kill Particles选项,粒子在碰撞后就会继续飞行,完全符合你的需求。
内容的提问来源于stack exchange,提问作者Game Lion
相关产品推荐
相关产品推荐

