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

Unity自定义粒子系统:新生成粒子立即销毁问题的解决

Unity粒子寿命共享问题解决办法

问题描述

从零构建Unity粒子系统时,设置粒子寿命为2秒后出现异常:初始粒子在2秒后正常销毁,但后续生成的粒子会立即被销毁,推测lifespan变量被所有粒子实例共享,需要让每个粒子拥有独立的寿命值。

问题根源

核心问题是预制体的public字段在运行时被修改后,新实例化的粒子会直接继承该修改后的剩余值。比如当你在Inspector中调整了预制体的lifespan,或者第一个粒子运行时消耗了这个公共字段的值,后续粒子拿到的就不是初始的2秒,而是已经被消耗后的0或负数,导致立即销毁。

解决步骤

  • 用私有实例变量存储每个粒子的剩余寿命,避免共享预制体的public字段值。
  • 在粒子实例初始化时(比如Start方法),将私有变量重置为初始寿命值,确保每个粒子都从完整寿命开始计算。

修改后的代码

Particle脚本(关键修改:分离初始寿命和当前剩余寿命)

using UnityEngine;

public class Particle : MonoBehaviour
{
    public Vector3 velocity;
    public Vector3 gravityAcceleration = new Vector3(0, -9.81f, 0);
    // 可在Inspector设置预制体的初始寿命默认值
    public float initialLifespan = 2f;
    // 私有变量存储当前实例的剩余寿命,每个粒子独立持有
    private float currentLifespan;

    void Start()
    {
        velocity = new Vector3(Random.Range(-2f, 2f), Random.Range(-2f, 2f), Random.Range(-2f, 2f));
        // 初始化当前粒子的剩余寿命为初始值
        currentLifespan = initialLifespan;
    }

    void Update()
    {
        // 更新运动状态
        velocity += gravityAcceleration * Time.deltaTime;
        transform.position += velocity * Time.deltaTime;

        // 减少当前粒子的剩余寿命
        currentLifespan -= Time.deltaTime;
        if (currentLifespan <= 0f) 
        {
            Destroy(gameObject);
        }
    } 
}

ParticleEmitter脚本(可选:统一控制初始寿命)

如果需要在发射器中统一调整所有粒子的初始寿命,可以修改Emitter脚本,在实例化时直接赋值:

using UnityEngine;

public class ParticleEmitter : MonoBehaviour {

    public GameObject particlePrefab;
    public float particleRate = 20f;
    public float timer = 0f;
    // 在这里统一设置所有粒子的初始寿命
    public float globalInitialLifespan = 2f;

    void CreateParticle() {
        GameObject particle = Instantiate(particlePrefab, transform.position, transform.rotation);
        Particle particleComp = particle.GetComponent<Particle>();
        if (particleComp != null)
        {
            // 覆盖预制体的初始寿命,使用发射器设置的值
            particleComp.currentLifespan = globalInitialLifespan;
        }
    }

    void Update()
    {
        timer += Time.deltaTime;
        
        if(timer >= 1f / particleRate) {
            CreateParticle();   
            timer = 0f;
        }
    }
}

额外优化点

  • 移除Particle脚本中无用的position字段,直接使用transform.position即可。
  • 删除Destroy前的this.gameObject != null判断,因为Update仅在物体激活状态下执行,此时物体必然存在。

内容的提问来源于stack exchange,提问作者Thanasis Mpoulionis

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 03:35:55