Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Placing points along a circular path relative to a rotation?

Discussion in 'Scripting' started by TheAlmightyPixel, Aug 22, 2016.

  1. TheAlmightyPixel

    TheAlmightyPixel

    Joined:
    Jun 21, 2014
    Posts:
    263
    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.

    Code (CSharp):
    1.  
    2. float angle = array.minAngle;
    3.  
    4.         for(int x=0; x<array.circleLayers; x++)
    5.         {
    6.             for(int i=0; i<array.circleClones; i++)
    7.             {
    8.                 angle += (array.maxAngle - array.minAngle) / array.circleClones;
    9.  
    10.                 Vector3 pos = transform.position;
    11.  
    12.                 pos.x += array.circleRadius * Mathf.Cos(angle * Mathf.Deg2Rad) + array.circleLayerOffset.x * x;
    13.                 pos.z += array.circleRadius * Mathf.Sin(angle * Mathf.Deg2Rad) + array.circleLayerOffset.z * x;
    14.                 pos.y += array.circleLayerOffset.y * x;
    15.  
    16.                 pos = transform.rotation * pos;
    17.             }
    18.         }
    19.  
    This is what the following code creates. The problem with this is that the drawn cubes don't follow the rotation of the gameobject.

    ss.jpg

    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?
     
    Last edited: Aug 22, 2016
  2. LeftyRighty

    LeftyRighty

    Joined:
    Nov 2, 2012
    Posts:
    5,148
  3. TheAlmightyPixel

    TheAlmightyPixel

    Joined:
    Jun 21, 2014
    Posts:
    263
    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.
     
  4. TheAlmightyPixel

    TheAlmightyPixel

    Joined:
    Jun 21, 2014
    Posts:
    263
    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.
     
  5. TJHeuvel-net

    TJHeuvel-net

    Joined:
    Jul 31, 2012
    Posts:
    817
    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.
     
  6. TheAlmightyPixel

    TheAlmightyPixel

    Joined:
    Jun 21, 2014
    Posts:
    263
    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.
     
  7. TJHeuvel-net

    TJHeuvel-net

    Joined:
    Jul 31, 2012
    Posts:
    817
    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.
     
  8. TheAlmightyPixel

    TheAlmightyPixel

    Joined:
    Jun 21, 2014
    Posts:
    263
    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!

    solution.gif
     
    Isam1212 likes this.
  9. TJHeuvel-net

    TJHeuvel-net

    Joined:
    Jul 31, 2012
    Posts:
    817
    Mind posting that code, so anyone that finds this thread in the future has a solution too?
     
  10. TheAlmightyPixel

    TheAlmightyPixel

    Joined:
    Jun 21, 2014
    Posts:
    263
    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.

    Code (CSharp):
    1. float angle = array.minAngle;
    2.  
    3.         for(int x=0; x<array.circleLayers; x++)
    4.         {
    5.  
    6.             for(int i=0; i<array.circleClones; i++)
    7.             {
    8.                 angle += (array.maxAngle - array.minAngle) / array.circleClones;
    9.                
    10.                 //The "transform.position" was replaced with "transform.localPosition"
    11.                 Vector3 pos = transform.localPosition;
    12.  
    13.                 pos.x += array.circleRadius * Mathf.Cos(angle * Mathf.Deg2Rad) + array.circleLayerOffset.x * x;
    14.                 pos.z += array.circleRadius * Mathf.Sin(angle * Mathf.Deg2Rad) + array.circleLayerOffset.z * x;
    15.                 pos.y += array.circleLayerOffset.y * x;
    16.  
    17.                 //The "transform.rotation" was replaced with "transform.localRotation"
    18.                 pos = transform.localRotation * pos;
    19.  
    20.                 clone.position = pos;
    21.  
    22.                 //The "transform.rotation" was replaced with "transform.localRotation"
    23.                 clone.rotation = transform.localRotation;
    24.             }
    25.         }
    If you have any specific questions, feel free to ask!
     
    mantie233 likes this.
  11. LeftyRighty

    LeftyRighty

    Joined:
    Nov 2, 2012
    Posts:
    5,148
    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?

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections.Generic;
    4.  
    5. public class Test : MonoBehaviour
    6. {
    7.     public Transform markerPrefab;
    8.     [Range(1, 100)]
    9.     public int pointCount;
    10.     public float radius;
    11.  
    12.     public List<Transform> markers;
    13.  
    14.  
    15.     public void Start()
    16.     {
    17.         markers = new List<Transform>();
    18.         InitMarkers();
    19.     }
    20.  
    21.     public void Update()
    22.     {
    23.         if (pointCount != markers.Count)
    24.         {
    25.             InitMarkers();
    26.         }
    27.      
    28.         ////// the core bit ///////
    29.         Quaternion quaternion = Quaternion.AngleAxis(360f / (float)(pointCount - 1), transform.up);
    30.         Vector3 vec3 = transform.forward * radius;
    31.         for (int index = 0; index < pointCount; ++index)
    32.         {
    33.             markers[index].position = transform.position + vec3;
    34.             // update for the next one
    35.             vec3 = quaternion * vec3;
    36.         }
    37.         ////// end of the core bit ///////
    38.     }
    39.  
    40.     private void InitMarkers()
    41.     {
    42.         if (pointCount > markers.Count)
    43.         {
    44.             for (int i = markers.Count; i < pointCount; i++)
    45.             {
    46.                 // doesn't matter, we're updating the positions later
    47.                 markers.Add(Instantiate(markerPrefab, Vector3.zero, Quaternion.identity) as Transform);
    48.             }
    49.         }
    50.         if (pointCount < markers.Count)
    51.         {
    52.             while (pointCount < markers.Count)
    53.             {
    54.                 Destroy(markers[0].gameObject);
    55.                 markers.RemoveAt(0); // dont miss this line out!!
    56.             }
    57.         }
    58.     }
    59. }
    60.  
    if they absolutely need to be vec3s then:
    Code (csharp):
    1.  
    2. // change
    3. markers[index].position = transform.position + vec3;
    4. // to
    5. markers[index] = transform.position + vec3;
    6.  
     
    tokar_dev likes this.
  12. TheAlmightyPixel

    TheAlmightyPixel

    Joined:
    Jun 21, 2014
    Posts:
    263
    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.
     
    LeftyRighty likes this.
  13. Isam1212

    Isam1212

    Joined:
    Feb 23, 2021
    Posts:
    3
    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
     
  14. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,043
    Please look at the dates.
     
    Bunny83 likes this.