Problem with Particle 3D Rotation Aligning to Center of Sphere

Hello!

I’m having some trouble with getting a single emission of 18,000 particles to rotate facing away from the center of a globe.

Because I don’t have access to the .LookAt() method that comes with a Unity transform component, I’m struggling to get each particle that is placed on the globe to rotate facing away from the center of the globe. I have tried using the emitParams.rotation3D and passing in a Quaternion.LookRotation(direction, Vector3.up).eulerAngles conversion but I get a strange result pictured below.

Below is part of the code that deals with initializing and positioning each emitted point on the globe.

public void InitializeParticleSystem()
    {
        pSystem = this.gameObject.AddComponent<ParticleSystem>();
        var rend = pSystem.GetComponent<ParticleSystemRenderer>();
        var em = pSystem.emission;
        var shape = pSystem.shape;
        var mainModule = pSystem.main;

        Material particleMaterial = Resources.Load("Point") as Material;
        pSystem.GetComponent<ParticleSystemRenderer>().material = particleMaterial;

        shape.enabled = false;
        em.rateOverTime = 0f;
        rend.alignment = ParticleSystemRenderSpace.World;
        mainModule.startSize = .01f;
        mainModule.startSpeed = 0;
        mainModule.startColor = new Color(255, 255, 255, 255);
        mainModule.maxParticles = nodeCount;
        mainModule.startLifetime = Mathf.Infinity;

        // Get each of the 18,000 position values represented in
        // latitude and longitude coordinates and convert them to Cartesian coordinates.
        foreach (var item in jsonObjects.rootNodes)
        {
            SetParticlePositionAndRotation(SphericalToCartesian(item.latitude, item.longitude));
        }

        if (m_Particles == null || m_Particles.Length < pSystem.main.maxParticles)
        {
            m_Particles = new ParticleSystem.Particle[pSystem.main.maxParticles];
        }
    }

    public void SetParticlePositionAndRotation(Vector3 particlePos)
    {
        var emitParams = new ParticleSystem.EmitParams();
        emitParams.position = particlePos;

        // Having trouble aglining particle to face away from center of the globe
        Vector3 direction = particlePos - this.transform.position;
        Quaternion rot = Quaternion.LookRotation(direction, Vector3.up);
        emitParams.rotation3D = rot.eulerAngles;

        pSystem.Emit(emitParams, 1);
    }

Here is an image of what happens with I run the code above. As you can see they are rotating weirdly and not a flat square on the surface.

Here is an image of what I’m trying to do with each particle emitted on the globe.

I have tried using the same code rotating just a flat plane/sprite and it works but when I implement it with each particle it does not work using the emitParams.rotation3D :frowning:

Any thoughts?

J

Have you tried messing with the rendering options “View” at all? That is, if the particle system is set to “View” or “Facing” , the particle system automatically tries to face the particles towards your camera. If you set it to world or local it might help.

I’m not that great at conceptualizing what people are trying to do, but just wanted to throw that out there if you havn’t played with those settings before.

Yes I feel like I have tried everything but nothing works :frowning:

Bump

Hi,

We support this behaviour without scripting, which will be far more efficient, but the full solution requires a feature in 2018.3 (ordered mesh emission), so depends what version you’re on.

I recommend:

  • bake the positions to a mesh in an editor script and save the mesh as an asset. Also bake a normal for the direction you want it to face (pos minus center normalised) there should be no need to assign anything to the triangles property
  • create a particle system and in the shape module set it to emit from this mesh
  • enable the align to direction option (also in the shape module)
  • also in the shape module, change Type from Vertex to Vertex Ordered
  • add a single burst of 18,000 particles

But if you’re not able to use 2018.3, reply and let me know, and I’ll share our “align to direction” code on Monday when I’m back in the office, which should make your script approach work :slight_smile:

It works perfectly! Thankfully I was using 2018.3. Thank you!

1 Like

I am curious to see the code if you don’t mind, is it something I was missing?

Sure, it’s something like this (i converted to C# for the example)

Vector3 x = new Vector3(normal.z,0.0f, -normal.x);                       // optimized equivalent of cross(Vector3.up, normal)
x = Vector3.normalizeSafe(x, new Vector3(0.0f, -normal.z, normal.y));    // if this gives a parallel vector, use optimized equivalent of cross(Vector3.right, normal) as fallback

float y = normal.z * x.x - normal.x * x.z;                               // we only need the y component of cross(normal, x)

rotation.x += Math.Atan2(-normal.y, y);
rotation.y += Math.Atan2(-x.z, -x.x);

It’s optimized in a few places, and handles the case where the desired direction (normal) is parallel to the world up vector, which would otherwise fail.

1 Like

Awesome! Thank you so much for your help.

1 Like