How to orient individual particles to their animated velocity vector?

I hope I am not duplicating the question, but, no matter how hard I researched and experimented, I found no conclusive answer or satisfying result. I refer to the shuriken particle system (not VFX) and how I could possibly orient each mesh particle (on which noise has been applied) (preferably by code), in a way that the particle’s local pivot is always aligned to the particle’s movement. My insight so far:

  • The particle’s movement generated by the Noise module is the particle.animatedVelocity vector. So I need to rotate the particle in way that it’s z local axis aligns to the direction of the former vector. (I don’t mind if the local y-vector faces up or down.)

  • I don’t want to use the predefined Render Alignment property set to “Velocity”, since I am using a vertex displacement shader that misbehaves, if I select any other than “Local” Render Alignment option. Hopefully, alignment to “Velocity” is not the only solution and I don’t have to edit the shader’s code, in order to be able to go down that road.

  • First,I am not sure how to affect each particle’s local orientation/rotation in the script. Second, I have tried several methods to do so, with one among them being to set the particle’s rotation3D to Quaterion.LookRotation.eulerAngles, but again this breaks the desired shader’s behavior. Third, it seems that the “Align to Direction” option in the “Shape” module does the proper job, without ruining the shader’s animation, but it is applied only at the emittion. I have not found any information though of the backround calculations regarding this function.

I run out of luck with this one and it gets so frustrating, so please any help is very appreciated!

First, enable Start Rotation 3D.
Now you can set an xyz rotation for the particle.
to set it, use ParticleSystem.GetParticles and ParticleSystem.SetParticles. There is a field for each particle to set its rotation value.
Finally, you need the code to set the xyz values based on a look direction. I’m sharing an adaptation of the engine code that does this, here:

float3 x = float3(n.z, 0.0f, -n.x);
x = normalizeSafe(x, float3(0.0f, -n.z, n.y));

float y = n.z * x.x - n.x * x.z;

rotation.x = atan2(-n.y, y);
rotation.y = atan2(-x.z, -x.x);
rotation.z = 0.0f;

where n is the desired look direction, and normalizeSafe is a normalize function that returns the second parameter as the result, in the case where the sq length is very close to zero.

remember, if you use animatedVelocity for n, normalize it first. and handle the case where the particle is not moving with some kind of normalizeSafe function: length(animatedVelocity) < epsilon