C# 为什么我不能在Start()方法之外使用ParticleSystem.Emit()?

C# 为什么我不能在Start()方法之外使用ParticleSystem.Emit()?,c#,unity3d,particle-system,C#,Unity3d,Particle System,我正在尝试使用ParticleSystem.Emit动态发射粒子,但无法使发射在Start方法之外工作 我可以在“开始”方法中发射粒子,可以直接发射,也可以使用单独的方法发射。当尝试在Update、LateUpdate或FixedUpdate中执行相同操作时,它将不再工作 没有报告任何错误。我在update方法中报告了粒子数,以确保那里的代码实际正在运行,并报告了我在Start方法中发射的粒子数 尝试在我尝试过的更新方法中发射粒子时: 在更新循环中直接使用Emit。 使用在更新循环中直接调用的单

我正在尝试使用ParticleSystem.Emit动态发射粒子,但无法使发射在Start方法之外工作

我可以在“开始”方法中发射粒子,可以直接发射,也可以使用单独的方法发射。当尝试在Update、LateUpdate或FixedUpdate中执行相同操作时,它将不再工作

没有报告任何错误。我在update方法中报告了粒子数,以确保那里的代码实际正在运行,并报告了我在Start方法中发射的粒子数

尝试在我尝试过的更新方法中发射粒子时:

在更新循环中直接使用Emit。 使用在更新循环中直接调用的单独方法。 在更新循环中使用名为Using Invoke的单独方法。 我能够在更新中检查和改变粒子位置,所以我不认为我有什么范围问题

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Test : MonoBehaviour
{
    public ParticleSystem aSystem;
    private ParticleSystem.Particle[] aParticle;

    void Start()
    {
        aParticle = new ParticleSystem.Particle[aSystem.main.maxParticles];

        // Emit particle.
        DoEmit();

        Debug.Log("Particle Count: " + aSystem.particleCount);
    }

    void Update()
    {
        int numParticles = aSystem.GetParticles(aParticle);
        Debug.Log("Number of particles: " + numParticles);
        for (int i = 0; i < numParticles; i++)
        {
            if (aParticle[i].position.z > 1)
            {
                aParticle[i].position = new Vector3(0f,0f,0f);
            }
            aParticle[i].velocity = new Vector3(0f, 0f, 1f);
        }
        aSystem.SetParticles(aParticle);

        // Emit particle.
        DoEmit();
    }

    void DoEmit()
    {
        // Configure render settings for particle.
        ParticleSystemRenderer aRenderer = aSystem.GetComponent<ParticleSystemRenderer>();
        aRenderer.renderMode = ParticleSystemRenderMode.Mesh;
        aRenderer.mesh = Resources.Load<Mesh>("vector");

        // Configure rest of settings and emit.
        var emitParams = new ParticleSystem.EmitParams();
        emitParams.startLifetime = 120;
        emitParams.position = new Vector3(0.0f, 0.0f, 0.0f);
        emitParams.velocity = new Vector3(0.0f, 0.0f, 0.0f);
        emitParams.startSize = 1;
        aSystem.Emit(emitParams, 1);
        aSystem.Play(); // Continue normal emissions
        Debug.Log("DoEmit() called!");
    }
}
预期结果:沿+z方向移动的粒子流


实际结果:一个粒子在+z方向移动。

我需要做一些类似的事情,发现它为我提供了一个伟大、可靠的解决方案,我多次重复使用并根据自己的目的进行修改。它是一个粒子池,您可以根据需要从中发射一个或多个粒子,杀死最后生成的粒子,并在达到最大粒子数后重新使用。我想这正是你想要的。为了清晰起见,我将在这里附上相关的脚本供参考,并附上作者丰富多彩的评论

请注意,此脚本是为Unity 2018.x编写的,但到2020.2.1时仍能正常工作

Artifact Jesse关于相当通用的粒子池的完整功能示例:

using UnityEngine;

[RequireComponent(typeof(ParticleSystem))]
public class ParticlePool : MonoBehaviour
{

 private int lastParticleIndex = 0;  // keeps track of our oldest particle (for deletion)

 // these will all be inited in Initialize() on Start()
 private ParticleSystem particleSys;             // our object's particle system
 private ParticleSystem.Particle[] particles;    // our reusable array of particles
 private ParticleSystem.EmitParams emitParams;   // reusable emitparams
 private int maxParticles = 0;       // total number of particles in our scene before re-using


 private void Awake()
 {
     Initialize(); // initialize all of our member variables
 }



 public void CreateParticle(Vector3 position, float size, Vector3 velocity, float angularVelocity)
 {
     // if we're at our particle count limit, kill our oldest particle.

     int activeParticles = particleSys.GetParticles(particles);
     /// this thing sucks. Read the Unity docs VERY carefully to understand...
     /// basically the parameter (particles) is an out parameter which will
     /// write out the existing particles in the particle system to our
     /// reusable array. After that, we can directly modify the particles
     /// and then when we're done, write the particles back into the
     /// particle system with ParticleSystem.SetParticles( particles, count )
     
     if (activeParticles >= maxParticles)
     {
         // set lifetime to -1 to kill the particle
         particles[lastParticleIndex].remainingLifetime = -1;
         // we need to reset start lifetime to a normal value, too or the particle will still have infinite lifetime
         particles[lastParticleIndex].startLifetime = 1;

         lastParticleIndex++;    // keep track of oldest particle
         if (lastParticleIndex >= maxParticles) lastParticleIndex = 0;

         // have to re-write
         particleSys.SetParticles(particles, particles.Length);  // write those pesky particles back into our ParticleSystem
     }


     // set up params for this particle, you can use whatever you want (see unity docs for EmitParams for what's available)
     emitParams.angularVelocity = angularVelocity;
     emitParams.position = position;
     emitParams.startSize = size;
     emitParams.velocity = velocity;
     emitParams.startLifetime = float.MaxValue; // float.MaxValue makes the particle's lifetime infinite

     particleSys.Emit(emitParams, 1);
     particleSys.Play();
 }


 void Initialize()
 {
     if (particleSys == null)
         particleSys = GetComponent<ParticleSystem>();

     maxParticles = particleSys.main.maxParticles;

     if (particles == null || particles.Length < particleSys.main.maxParticles)
         particles = new ParticleSystem.Particle[particleSys.main.maxParticles];
 }
}


注意:本例中的粒子系统只是带有渲染器的裸mininum。不循环,唤醒时不启动,模拟空间设置为世界。上面的脚本尊重MaxParticles。

您是否在没有aSystem.Play的情况下尝试过它;?不确定,但可能是每帧都重新启动粒子系统?@derHugo是的,我试着对aSystem.Play进行评论。我还尝试了转换系统。使用DoEmit方法。这两件事都不管用。粒子系统可能正在重新启动,我想这是显而易见的,因为我的粒子是在原点创建的,并且允许粒子在多个帧上移动一段距离。你能想出比只看游戏窗口上的向量更好的测试方法吗?