Hi! I’m making a custom particle system where the particles orbit around the center of the system like stars around a galaxy. To do this, I implemented the code below. It works well, but when I have a lot of particles, the framerate gets slowed way down because the for loop has to run thousands of times. I figured a coroutine might be a good option to speed things up. I have to put the function in update so I set it up to only run the coroutine again once the previous run has completed. I also put the yield statement inside the for loop because I need Unity to be able to stop the for loop and move onto the next frame before picking it back up.
Something is wrong, though, because when I run this code, none of my particles update their position. I’m pretty sure that it is never even entering into the for loop. Does anyone know what I did wrong here? Thanks.
private void Update()
{
if (!isUpdating) //Note: isUpdating is set to false on start.
{
StartCoroutine(UpdatePosition());
isUpdating = true;
}
}
IEnumerator UpdatePosition()
{
// GetParticles is allocation free because we reuse the m_Particles buffer between updates
numParticlesAlive = m_System.GetParticles(m_Particles);
// Change only the particles that are alive
for (int i = 0; i < numParticlesAlive; i++)
{
Debug.Log(i);
m_Particles[i].velocity = new Vector3(0, 0, 0);
float r = m_Particles[i].position.magnitude;
float T = 2 * Mathf.PI * Mathf.Sqrt(Mathf.Pow(r, 3.0f) / GM);
float Theta_dot = 360f / T;
float Theta_new = Theta_dot * Time.deltaTime * timeMultiplier;
m_Particles[i].position = Quaternion.Euler(0, Theta_new, 0) * m_Particles[i].position;
yield return null;
}
// Apply the particle changes to the particle system
m_System.SetParticles(m_Particles, numParticlesAlive);
isUpdating = false;
}
Okay, that seemed to fix the problem of it not entering the for loop.
But now I’m having a different issue. It seems like the for loop is not being picked back up where it left off. The highest it gets is a few hundred. Any thoughts on what might be happening here?
numParticlesAlive = m_System.GetParticles(m_Particles); is getting updated every time it goes back to the coroutine. try removing it and passing a variable you assign right before the coroutine starts
I just tried it and I am still having the same issue. The coroutine is restarting the loop at the beginning every time. Maybe I am just misunderstanding coroutines, but I thought it was supposed to pick up where it left off.
This seems to be working. numParticlesAlive needed to be at the beginning of update. So now it is working as intended, but for some reason the loop is running extremely slow. I figured it would just spread out the UpdatePosition function over a few frames, but it is taking minutes in real time to run through the loop.
private void Update()
{
numParticlesAlive = m_System.GetParticles(m_Particles);
if (!isUpdating) //Note: isUpdating is set to false on start.
{
StartCoroutine(UpdatePosition());
}
}
yield return null returns control to unity after every frame you may need one that does it after a few secs or add a variable to time it. like say only return null after timer = 100 then set it back to 0