- Home /
Emit particles throughout a line/ray?
Hello all,
I've been banging my head for the past weeks with this. I'm trying to spawn particles along a line (point A to point B). Those two points would update dynamically. The idea is to create a laser beam without using the linerenderer. So far I've tried creating a mesh at runtime with only two vertices, then assigning it to the emitter's shape, but I get very strange results with orientation. I've also tried exporting just a single edge mesh, which I had to run through a custom importer to bypass Unity welding loose vertices, but I'm still getting very strange artifacts... I'm kinda lost.
So the question is:
Do any of you know of a method for doing this?
What Im looking for is to have an Edge emitter but be able to control the start and end points and not just the radius.
I'd appreciate any pointers. Thanks in advance!
Edit: This question is exactly what I mean. But the Line primitive doesn't exist anymore, apparently.
Answer by richardkettlewell · Sep 15, 2019 at 08:02 PM
I would use the Edge in the Shape module, set the radius based on the distance between the end and start position, then set the Transform within the Shape Module to make the line look form the start to the end position. To do this, set the position to the line start position, leave the scale as 1,1,1, and set the rotation to look towards the end position by using https://docs.unity3d.com/ScriptReference/Quaternion.LookRotation.html
Probably the up vector argument can be the default up: 0,1,0. And remeber that it’s relative to the start position, so use endpos-startpos for the target position.
Bonus advice: use Burst emission and Burst Spread mode in the shape module to distribute particles evenly along the line!
Good luck!
Thank you, at my earliest attempts, I had considered something like this, but I lacked the insight to solve the radius/distance problem.
So, following your advice, now I'm doing radius = distance and offsetting the Shape's position by half of that distance. Lenght is fine, rotation works, but I'm not getting consistent behaviour with the 'start point' , since the middle point of the edge shifts around depending on the distance. Now, logic would say it'd be enough with the offset, but for some reason it's not. Perhaps I'm missing something?
Regarding what you said about 'setting the position to the line start position', what did you mean exactly? I'm not clear on that, could you explain a bit more?
Oh, burst spread tip was really neat, too. Thanks a bunch for everything :)
I forgot the Edge extends in both directions. So you’re right - the position in the shape transform position needs to be the midpoint ((end-start)*0.5f)
Ok, I got it working... mostly.
After a lot of exa$$anonymous$$ation, it turns out that I was treating the radius as the diameter (buuuuh).
For future-proof then, end result goes something like this: Edge radius = distance / 2, Shape's Z position = radius. I added an edge offset variable for fine tuning to shrink the start/end by substracting it from the radius and adding it to the position.
Thanks a lot, friend! You've helped me clear up a lot of weeks' stagnancy.
Cheers!
Answer by redemptioner · Mar 02 at 05:44 AM
Here is some code using richardkettlewell's idea that works in my project:
ParticleSystem theSystem = ....
Vector3 startPosition = ...
Vector3 endposition = ...
Vector3 particlePosition = ( endposition - startPosition) / 2 + startPosition; // particle system position is delta middle + start position
float distance = Vector3.Distance(endposition, startPosition) /2; //distance is half the total distance since line extends both ways
int numParticles = (int)(distance * 100);
theSystem.transform.position = particlePosition; //update the system's position
theSystem.transform.LookAt(endposition); //adjust the look rotation. NOTE: the particle system has a y rotation of 90 in the shape module for this to work.
ParticleSystem.ShapeModule sm = theSystem.shape;
sm.radius = distance; //adjust the line size
ParticleSystem.EmissionModule em = theSystem.emission;
ParticleSystem.Burst b = new ParticleSystem.Burst(0, numParticles);
em.SetBurst(0, b); //set burst to be the number of desired particles.
if (theSystem .isPlaying)
{
theSystem .Stop();
}
theSystem .Play();