You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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);
    }
}

关键细节解释

  1. 为什么用HashSet而不是List存hitObjects?
    HashSet的Contains方法查找效率比List高,尤其是当你有很多敌方单位时,性能更好。当然如果你的场景敌人不多,用List也没问题。

  2. GetTriggerParticles和SetTriggerParticles的作用
    ParticleSystem的触发事件是批量处理的,GetTriggerParticles会把当前帧所有触发指定事件(这里是Enter)的粒子和碰撞体取出来,处理完后必须用SetTriggerParticles把粒子状态回传给系统,否则会出现重复触发的问题。

  3. 空安全判断
    用TryGetComponent代替直接GetComponent,可以避免当敌方对象没有实现IDamageable接口时报空引用错误,让代码更健壮。

  4. 粒子继续飞行的保障
    只要你在Trigger模块里没有勾选Kill Particles选项,粒子在碰撞后就会继续飞行,完全符合你的需求。

内容的提问来源于stack exchange,提问作者Game Lion

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 16:32:41