【Unity】unity 粒子触发器

本文介绍了一种在游戏中实现水枪粒子触发与碰撞的方法。通过使用Unity中的ParticleSystem组件,并配合自定义脚本ParticleXFBase,实现了粒子触发时的事件回调功能。文章详细解释了如何设置粒子系统的触发器和碰撞器,以及如何检测粒子与目标物之间的碰撞。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

项目中有时候会用到粒子碰撞或者触发,比如水枪打到哪里 需要打到的时候有方法回调


水枪粒子的设置


这里要注意的是Collision 和 Triggers


在水枪粒子身上有一个脚本

ParticleXFBase

#region Gavin

using System.Collections.Generic;
using UnityEngine;

#endregion
/// <summary>
/// 消防粒子
/// </summary>
public class ParticleXFBase : MonoBehaviour
{
    protected ParticleSystem PS;
    private GameObject Foam;
    private bool _isOpened;         //水阀是否打开

    public Vector3 StartPoint;
    //    public Vector3 Destination;
    public float ShotSpeed;
    public float LifeTime;


    public GameObject XFTarget { get; set; }
    public string FireGunPoint { get; set; }
    public double PointValue { get; set; }

    private int _triggerThreshold = 30;

    private float _ffTimer;                         //消防计时器     
    protected float Interval = 1.0f;                //两次喷上的间隔时间(默认)
    protected bool IsSendPoint = false;                     //消防炮评分是否发送过

    List<ParticleSystem.Particle> enter = new List<ParticleSystem.Particle>();
    List<ParticleSystem.Particle> exit = new List<ParticleSystem.Particle>();
    List<ParticleSystem.Particle> inside = new List<ParticleSystem.Particle>();
    List<ParticleSystem.Particle> outside = new List<ParticleSystem.Particle>();

    public int TriggerThreshold
    {
        get { return _triggerThreshold; }
        set { _triggerThreshold = value; }
    }

    public void ToggleWater(bool isOpen)
    {
        IsSendPoint = false;
        gameObject.SetActive(isOpen);
    }

    public virtual void Init()
    {
        transform.localPosition = Vector3.zero;
        transform.localEulerAngles = Vector3.zero;
        //****************核心代码
        PS = GetComponent<ParticleSystem>();
        if (XFTarget != null)
            PS.trigger.SetCollider(0, XFTarget.GetComponentInChildren<Collider>(true));
        //*******************
        var mainModule = PS.main;
        {
            mainModule.startSpeed = ShotSpeed;
            mainModule.startLifetime = LifeTime;
        }

    }

    //    protected virtual void OnParticleCollision(GameObject other)//检测到粒子碰撞
    //    {
    //        if (_isOpened == false) return;
    //
    //        if (other.CompareTag(XFTarget))//消防炮粒子需要增加XFP的Tag
    //        {        
    //            if (IsSendPoint) return;
    //            Debug.LogFormat("{0}___粒子来袭..", XFTarget);
    //            _ffTimer += Time.deltaTime;
    //            if (_ffTimer >= Interval)//连续检测到火粒子的碰撞时间差小于fDeltaTime
    //            {
    //                _ffTimer -= Interval;
    //                DataCommModule.Instance.SetPointValue(FireGunPoint, PointValue, RoleManager.Instance.currentRoleID, 1);
    //                Debug.LogFormat("{0}________发送了点值..", XFTarget);
    //                IsSendPoint = true;
    //            }
    //        }
    //    }
    private int debugCount = 0;
    protected virtual void OnParticleTrigger()
    {
        int enterNum = PS.GetTriggerParticles(ParticleSystemTriggerEventType.Enter, enter);
        int exitNum = PS.GetTriggerParticles(ParticleSystemTriggerEventType.Exit, exit);
        int insideNum = PS.GetTriggerParticles(ParticleSystemTriggerEventType.Inside, inside);
        int outsideNum = PS.GetTriggerParticles(ParticleSystemTriggerEventType.Outside, outside);

        if (enterNum > 0)
            OnEnterCollider(enter);
        if (exitNum > 0)
            OnExitCollider(exit);
        if (insideNum > 0)
            OnInSideCollider(inside);
        if (outsideNum > 0)
            OnOutSideCollider(outside);
#if UNITY_EDITOR

        //        if (debugCount <= 1)
        //        {
        //            Debug.Log("insideNum" + insideNum + " inside.Count" + inside.Count);
        //            Debug.Log("enterNum" + enterNum + " enter.Count" + enter.Count);
        //            Debug.Log("exitNum" + exitNum + " exit.Count" + exit.Count);
        //            Debug.Log("outsideNum" + outsideNum + " outside.Count" + outside.Count);
        //            debugCount++;
        //        } 
#endif
        PS.SetTriggerParticles(ParticleSystemTriggerEventType.Enter, enter);
        PS.SetTriggerParticles(ParticleSystemTriggerEventType.Exit, exit);
        PS.SetTriggerParticles(ParticleSystemTriggerEventType.Inside, inside);
        PS.SetTriggerParticles(ParticleSystemTriggerEventType.Outside, outside);
    }

    private void FixedAction()
    {
        if (IsSendPoint) return;

        _ffTimer += Time.deltaTime;

        if (_ffTimer >= Interval)
        {
            _ffTimer -= Interval;
            int id = RoleManager.Instance.currentRoleID;
            DataCommModule.Instance.SetPointValue(FireGunPoint, PointValue, id, 1);

            IsSendPoint = true;
            Debug.LogFormat("________发送了点..{0}值{1}", FireGunPoint, PointValue);
        }
    }
    public virtual void OnEnterCollider(List<ParticleSystem.Particle> enters) { }
    public virtual void OnExitCollider(List<ParticleSystem.Particle> exits) { }
    public virtual void OnInSideCollider(List<ParticleSystem.Particle> insides)
    {
        Debug.Log("Cc");
        if (insides.Count > _triggerThreshold)
        {
            FixedAction();
        }
    }
    public virtual void OnOutSideCollider(List<ParticleSystem.Particle> outsides) { }



}
光靠单纯的碰撞是不行 在代码中需要指定

  PS = GetComponent<ParticleSystem>();
        if (XFTarget != null)
            PS.trigger.SetCollider(0, XFTarget.GetComponentInChildren<Collider>(true));
这里的XFTarget 就是下图中的 Cube 碰撞器



这样的话粒子如果打到就会进入回调  

 public virtual void OnInSideCollider(List<ParticleSystem.Particle> insides)


### Unity 粒子系统与触发器交互教程 在 Unity 中实现粒子系统与触发器的交互功能,可以通过 **Trigger 模块** 来完成。此模块允许开发者定义当粒子进入或退出 Collider 范围时的行为[^1]。 #### 配置 Trigger 模块 要在粒子系统中启用触发器交互,需执行以下操作: 1. 打开粒子系统的 Inspector 窗口并找到 **Collider** 或 **Trigger** 模块。 2. 启用该模块并通过其属性设置所需的交互行为。 3. 使用 `Collision` 或 `Trigger` 类型指定何时激活子发射器或其他事件响应逻辑[^2]。 #### 设置模拟空间 为了确保粒子系统能够正确检测到与其他对象的交互,需要合理选择模拟空间(Simulation Space)。如果目标是对全局环境中的物体进行反应,则应选用世界空间;而针对局部范围内的粒子间互动则更适合采用局部空间[^3]。 #### 实现具体效果 下面是一个简单的例子展示如何利用 C# 编写脚本来控制基于触发条件下的粒子表现变化: ```csharp using UnityEngine; public class ParticleTriggerExample : MonoBehaviour { private ParticleSystem ps; void Start() { ps = GetComponent<ParticleSystem>(); var triggerModule = ps.triggers; // 获取 Triggers 模块实例 if (triggerModule.enabled) { Debug.Log("Particle system triggers are enabled."); foreach(var t in triggerModule.triggers) { switch(t.triggerEvent){ case ParticleSystemTriggerEventType.Enter: Debug.Log("Particles entering the collider will be handled here."); break; case ParticleSystemTriggerEventType.Exit: Debug.Log("Particles exiting the collider will be processed accordingly.");break; default: continue; } } }else{Debug.LogWarning("Triggers not active");} } } ``` 上述代码片段展示了如何访问粒子系统的触发器集合,并依据不同的触发事件打印日志消息[^4]。 ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Unity_阿黄

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值