Placing points along a circular path relative to a rotation?

Hi,
So I’ve been trying to get this to work for some time now – basically what I’m trying to do is get a predetermined amount of points along a circular path and draw gizmos on them.

Now this is the code I’m using to simply create the circle path on a XZ plane.

float angle = array.minAngle;

        for(int x=0; x<array.circleLayers; x++)
        {
            for(int i=0; i<array.circleClones; i++)
            {
                angle += (array.maxAngle - array.minAngle) / array.circleClones;

                Vector3 pos = transform.position;

                pos.x += array.circleRadius * Mathf.Cos(angle * Mathf.Deg2Rad) + array.circleLayerOffset.x * x;
                pos.z += array.circleRadius * Mathf.Sin(angle * Mathf.Deg2Rad) + array.circleLayerOffset.z * x;
                pos.y += array.circleLayerOffset.y * x;

                pos = transform.rotation * pos;
            }
        }

This is what the following code creates. The problem with this is that the drawn cubes don’t follow the rotation of the gameobject.

I tried messing around with transform.forward and transform.right vectors to use the gameobject’s rotation as a guide for the Sin and Cos functions but it resulted in an odd oval shape with uneven spacing.

Any ideas how I could align the drawn cubes to the rotation of the gameobject?

you might be interested in

But that only rotates the gameobject? The points aren’t transforms, they’re Vector3’s.

I feel like this gif could explain my issue better:

What the code does now is that it places the cubes on the circle evenly, but the cubes don’t follow the rotation of the gameobject, which is the problem I’m currently facing.

So, I need to modify my code, but I have no idea how.

Okay, I think I got it. I swapped some of the transform.rotation and transform.position references with their local equivalents, and now the cubes are rotating nicely.

You’ll want the cubes to be parented by the object, and set the local position instead of the world position. Right now you say “I want this object to be 5,4 from the center of the world”, that i world position. What you want to say is “i want this object to be 5,4 from the center of my parent”, that is local space. Local is relative to his parent, until there is none. Then its relative to the world again.

The cubes are currently just Gizmos, not real objects, so they don’t follow the gameobject’s rotation. I guess I should’ve stated that in my post, sorry. I’ll edit my OP.

Ah right, in that case add this magical line at the start of your OnDrawGizmos:

Gizmos.matrix = transform.localToWorldMatrix;

It basicly does the same, from now on all Gizmos are in local space of the object.

I got it working without having to do anything with Gizmos, I simply made some changes to the Vector3’s that the Gizmos are using as their positions. It’s working well now, but I’ll keep your suggestion in mind, thanks!

2760840--199334--solution.gif

1 Like

Mind posting that code, so anyone that finds this thread in the future has a solution too?

Sure. I can’t post my full code, but this part has all the things that affected the behaviour of the Gizmos. Really the only way the code differs from what it was is using local rotations and positions instead of global.

float angle = array.minAngle;

        for(int x=0; x<array.circleLayers; x++)
        {

            for(int i=0; i<array.circleClones; i++)
            {
                angle += (array.maxAngle - array.minAngle) / array.circleClones;
                
                //The "transform.position" was replaced with "transform.localPosition"
                Vector3 pos = transform.localPosition;

                pos.x += array.circleRadius * Mathf.Cos(angle * Mathf.Deg2Rad) + array.circleLayerOffset.x * x;
                pos.z += array.circleRadius * Mathf.Sin(angle * Mathf.Deg2Rad) + array.circleLayerOffset.z * x;
                pos.y += array.circleLayerOffset.y * x;

                //The "transform.rotation" was replaced with "transform.localRotation"
                pos = transform.localRotation * pos;

                clone.position = pos;

                //The "transform.rotation" was replaced with "transform.localRotation"
                clone.rotation = transform.localRotation;
            }
        }

If you have any specific questions, feel free to ask!

1 Like

AngleAxis is a static function which generates a Quaternion… you can use that quaternion as you like.

that’s fairly irrelevant to the issue, the vectors are going to be applied to the objects you want at those points, so why have a vector3 list/array and not just have a transform array?

using UnityEngine;
using System.Collections.Generic;

public class Test : MonoBehaviour
{
    public Transform markerPrefab;
    [Range(1, 100)]
    public int pointCount;
    public float radius;

    public List<Transform> markers;


    public void Start()
    {
        markers = new List<Transform>();
        InitMarkers();
    }

    public void Update()
    {
        if (pointCount != markers.Count)
        {
            InitMarkers();
        }
      
        ////// the core bit ///////
        Quaternion quaternion = Quaternion.AngleAxis(360f / (float)(pointCount - 1), transform.up);
        Vector3 vec3 = transform.forward * radius;
        for (int index = 0; index < pointCount; ++index)
        {
            markers[index].position = transform.position + vec3;
            // update for the next one
            vec3 = quaternion * vec3;
        }
        ////// end of the core bit ///////
    }

    private void InitMarkers()
    {
        if (pointCount > markers.Count)
        {
            for (int i = markers.Count; i < pointCount; i++)
            {
                // doesn't matter, we're updating the positions later
                markers.Add(Instantiate(markerPrefab, Vector3.zero, Quaternion.identity) as Transform);
            }
        }
        if (pointCount < markers.Count)
        {
            while (pointCount < markers.Count)
            {
                Destroy(markers[0].gameObject);
                markers.RemoveAt(0); // dont miss this line out!!
            }
        }
    }
}

if they absolutely need to be vec3s then:

// change 
markers[index].position = transform.position + vec3;
// to
markers[index] = transform.position + vec3;
1 Like

I modified my OP a while ago – my goal was indeed to distribute points along the circle, and I managed to get it work. I know I could’ve been clearer in my first post, but at the time I felt like the info I left out wouldn’t have meant a thing.

Thanks for the info on Quaternions, They’re something I’ve rarely had to use so I don’t know much about them.

I might come back to this thread in case I do some changes to the script or if it breaks, but for now I’ve got it sorted.

1 Like

hi in fact i have tried your code with unity 2020 but it did not work, i’m trying to make electrons go around atom can you help please thank you

Please look at the dates.

1 Like