Hi, my Unity skills are pretty basic, but I’m hoping this has a simple solution though.
Is there some way I can ensure my particles do not spawn ontop of one another?
I don’t mind them colliding/blending into each other after they have spawned, as they are slow (they barely move) and this wouldn’t happen often, I just would like them not to spawn ontop of each other, is there a simple way in the particle system setup to do this?
If you mean preventing particles emitted by the same particle system from popping over each other, you can change the “sort mode” in renderer module to either youngest or oldest in front.
Thanks for the reply, however my particles are semi-transparent and differing sizes, so I still have the an issue when particles are spawned on top of each other.
Is there any method I can use to tell the particle system not to create a particle where there is one already?
Now I understand your goal, but it’s impossible without custom script. It requires comparing the Vector3.Distance minus target range of each new particle’s position with all other existing particles’ in a loop. The biggest problem is there is no way to efficiently determine where to move the particle until it is no longer within range of all other existing particles and subsequently redo the range check loop again. It just doesn’t sound very efficient to me. So I would say just don’t bother. The shape module provides some way to emit the particles in a formation like a circular loop for cone edge or circle edge, can’t guarantee these suit your need…
Keep in mind the following code just randomly moves the particle in hope of avoiding overlapping before running out of retries. If you want the cheaper option: killing overlapping particle straightaway, uncomment the color and lifetime = 0 codes, remove the r/retry variables and the while loop. The killing method will result in uneven particle emission visually (the dead particle still used up an emission count, because you can’t change the behavior of a particle before it’s born.)
using UnityEngine;
using System.Collections;
[RequireComponent(typeof(ParticleSystem))]
public class killOverlappingParticle : MonoBehaviour {
public float extraDistance = 0;
public int retry = 10;
public Vector3 retryRange;
ParticleSystem m_System;
ParticleSystem.Particle[] m_Particles;
private void LateUpdate() {
InitializeIfNeeded();
// GetParticles is allocation free because we reuse the m_Particles buffer between updates
int numParticlesAlive = m_System.GetParticles(m_Particles);
// Change only the particles that are alive
for (int i = 0; i < numParticlesAlive; i++) {
if (m_Particles[i].startLifetime - m_Particles[i].lifetime < 0.05f && retry > 0) {// Before Unity 5.5.
//if (m_Particles[i].startLifetime - m_Particles[i].remainingLifetime < 0.05f && retry > 0) {// Unity 5.5+.
for (int j = 0; j < numParticlesAlive; j++) {
if (i != j) {// Prevents the same particle compares to itself.
float dist = Vector3.Distance(m_Particles[i].position, m_Particles[j].position) - m_Particles[i].size - m_Particles[j].size - extraDistance;
if (dist < 0) {
/* // Using the killing method can remove retry and r variables and the following while loop.
m_Particles[i].color = new Color(0,0,0,0);// Reduce alpha to zero before killing it to avoid flickering.
m_Particles[i].lifetime = 0;// Kill the particle.
*/
int r = 0;
while (dist < 0 && r < retry) {
m_Particles[i].position += new Vector3(Random.Range(-retryRange.x,retryRange.x),Random.Range(-retryRange.y,retryRange.y),Random.Range(-retryRange.z,retryRange.z));
dist = Vector3.Distance(m_Particles[i].position, m_Particles[j].position) - m_Particles[i].size - m_Particles[j].size - extraDistance;
r++;
}
}
}
}
}
}
// Apply the particle changes to the particle system
m_System.SetParticles(m_Particles, numParticlesAlive);
}
void InitializeIfNeeded() {
if (m_System == null)
m_System = GetComponent<ParticleSystem>();
if (m_Particles == null || m_Particles.Length < m_System.maxParticles)
m_Particles = new ParticleSystem.Particle[m_System.maxParticles];
}
}
Wow, thanks for the thorough responses, I think some of these suggestions are a little too complex for me at this stage, I think I will come back to this problem when I have more confidence.
What I might do for now is turn down the number of particles, as this reduces the risk of overlap and I probably have too many anyway!
I have come across another more important problem, also related to particles and collisions, (not sure if I should start a new thread for this?)
I am using particles to create a thruster trail/smoke for a spaceship. It’s working nicely, however when thrusters are on and the ship is close to the ground Id really like the particles to perhaps collide with the ground (and kind of disperse outwards, if you can imagine a rocket ship taking off.
I found the legacy World Particle Collider and added it to my particle objects and it didn’t work so I did a search and I read that this can only be achieved using a plane, so I placed a plane where my ground collider is, but that doesn’t seem to make any difference either, the particles continue down and over the ground sprite, is there a good (and efficient) way to achieve this affect I am going for?
Btw I am using 3D models but a 2D perspective, so I have been using a 2D ground sprite intersected with a plane on the Z axis to try to create the collision with the particle system.
First we need to confirm which version of Unity editor you’re using. Supposedly the latest version has removed all legacy particle system components and Unity will not respond to any technical issue of the legacy component.
To answer your question about the thruster, assuming you use the non-legacy particle system, the emitter Shape should be a cone with non-zero degree cone angle. Enable Collision module with minimal bounce (0.1), some damping would help. Then you have 2 options, either use the default “plane” collision mode which collides all particles against an imaginery flat plane, this requires assigning any object represents the center position of the
plane. If nothing fits, just create an empty object, reposition it properly and assign it to particle collision module. This is cheap and guarantees no particle slips through the plane. Or you use “world” collision mode which requires setting up either mesh/sphere/capsule colliders on the object to be collided against but it’s less reliable, mesh collider is the worst offender.