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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Question Vector3 positions unaligned when rotating with Quaternion.AngleAxis

Discussion in 'Scripting' started by InacioM, Jun 28, 2020.

  1. InacioM

    InacioM

    Joined:
    Jun 19, 2019
    Posts:
    36
    Hey people, I've got a problem.

    I'm trying to set up a hexagonal grid in an radial fashion.

    The problem is, the corners don't align.



    Here's the code:

    Code (CSharp):
    1. public static class HexMetrics
    2. {
    3.     public const float cellRadius = 10f;
    4.  
    5.     public const float edgeDistance = cellRadius * 0.8660254037844386f;
    6.  
    7.     public const float centerDistance = edgeDistance * 2f;
    8.  
    9. }
    Code (CSharp):
    1.  
    2. public class HexGrid : MonoBehaviour
    3. {
    4.     Vector3[] centers;
    5.  
    6.     [SerializeField, Range(1, 10)]
    7.     int gridRadius;
    8.  
    9.     [SerializeField]
    10.     HexCell cellPrefab;
    11.  
    12.     int cellCount;
    13.  
    14.     HexCell[] cells;
    15.  
    16.  
    17.  
    18.     void Start()
    19.     {
    20.         cellCount = 1 + gridRadius * (gridRadius + 1)/2 * 6;
    21.         cells = new HexCell[cellCount];
    22.         centers = new Vector3[cellCount];
    23.  
    24.         StartCoroutine(AssignCenters());
    25.     }
    26.  
    27.     IEnumerator AssignCenters() {
    28.  
    29.         yield return new WaitForSeconds(0.5f);
    30.         cells[0] = Instantiate(cellPrefab, transform, false);
    31.         cells[0].transform.localPosition = centers[0] = transform.localPosition;
    32.  
    33.         cells[0].SetCorners();
    34.  
    35.         for (int ring = 1, i = 1; ring <= gridRadius; ring++) {
    36.             int ringCells = ring * 6;
    37.  
    38.             for (int c = 0; c < ringCells; c++, i++) {
    39.                 cells[i] = Instantiate(cellPrefab, transform, false);
    40.                 cells[i].transform.localPosition = centers[i] = Quaternion.AngleAxis((360 / ringCells) * c, Vector3.up) * transform.forward * HexMetrics.centerDistance * ring;
    41.  
    42.                 cells[i].SetCorners();
    43.                 yield return new WaitForSeconds(0.2f / ring);
    44.             }
    45.         }
    46.     }
    47.  
    48.     private void OnDrawGizmos() {
    49.  
    50.         Gizmos.color = Color.red;
    51.  
    52.  
    53.         for (int i = 1; i < cellCount; i++) {
    54.             if (!cells[i]) {
    55.                 return;
    56.             }
    57.             for (int j = 0; j < 6; j++) {
    58.                 Gizmos.DrawSphere(cells[i].corners[j], 1f);
    59.             }
    60.         }
    61.     }
    62.  
    63. }
    64.  
    Code (CSharp):
    1. public class HexCell : MonoBehaviour
    2. {
    3.     public Vector3[] corners;
    4.  
    5.     public void SetCorners() {
    6.  
    7.         /*
    8.         for (int i = 0; i < corners.Length; i++) {
    9.             corners[i] = transform.localPosition + HexMetrics.corners[i];
    10.         }
    11.         */
    12.  
    13.         for (int i = 0; i < corners.Length; i++) {
    14.             corners[i] = transform.localPosition + Quaternion.AngleAxis(30 + 60 * i, Vector3.up) * Vector3.forward * HexMetrics.cellRadius;
    15.         }
    16.     }
    17.  
    18. }
    I plan on moving the angle math to the HexMetrics function and just plugging in after localPosition.

    I've tried a non-radial approach as well, and the result was the same.


    Code (CSharp):
    1.  
    2.     public static Vector3[] corners = {
    3.         new Vector3(cellRadius * 0.5f, 0f, edgeDistance),
    4.         new Vector3(cellRadius, 0f, 0f),
    5.         new Vector3(cellRadius * 0.5f, 0f, -edgeDistance),
    6.         new Vector3(-cellRadius * 0.5f, 0f, -edgeDistance),
    7.         new Vector3(-cellRadius, 0f, 0f),
    8.         new Vector3(-cellRadius * 0.5f, 0f, edgeDistance)
    9.     };
    This leads me to believe the problem is when setting up the center position via rotation.
     

    Attached Files:

  2. MatrixQ

    MatrixQ

    Joined:
    May 16, 2020
    Posts:
    87
    It's hard to tell from the picture, but it seems that they are all slanted a bit to the same side. Could it be that your Prefab is slanted in itself, so it is drawing the corners correctly based on the rotation around the axis, only the axis in itself is slanted.

    Another thing, the centers don't seem to align all that well to begin with. Are you sure your math is correct on that? I don't think you can have equal angles beyond the first layer.

    I would probably first draw the six corners as long as they need to be, not the full circles. From there, you can fill in the rings in a straight line starting from the corners. I think that'll give you a bit more control over what goes where.
     
    InacioM likes this.
  3. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,735
    As a debugging tool it might be easier to visualize what's wrong if you give each hex its own random color to use for its corners. Right now I can't tell which corner belongs to which hex.
     
    InacioM likes this.
  4. InacioM

    InacioM

    Joined:
    Jun 19, 2019
    Posts:
    36
    Hey, guys. Thanks for jumping in to the rescue.

    While writing my report to explain the logic behind my math to you guys, I found my mistake.

    While the angles were right, the distances were not. The distance from the center of a hexagonal grid to another cell center is only the ring times the distance between centers if, and only if, it's a straight line of cells.



    In the picture above, the math was correct only for the black lines, the red ones were wrong.

    So, instead of calculating the distances from the center, I calculated the distances from the previous cell, setting only the first cell on each ring based on distance from the center (since it's always a straight line).

    Here's the code that worked:
    Code (CSharp):
    1.  
    2.     IEnumerator AssignCenters() {
    3.  
    4.         yield return new WaitForSeconds(0.5f);
    5.         cells[0] = Instantiate(cellPrefab, transform, false);
    6.         cells[0].transform.localPosition = centers[0] = transform.localPosition;
    7.  
    8.         cells[0].SetCorners();
    9.  
    10.         for (int ring = 1, i = 1; ring <= gridRadius; ring++) {
    11.             int ringCells = ring * 6;
    12.  
    13.             cells[i] = Instantiate(cellPrefab, transform, false);
    14.  
    15.             cells[i].transform.localPosition = centers[i] = Vector3.forward * HexMetrics.centerDistance * ring;
    16.  
    17.             i++;
    18.             HexDirection direction = HexDirection.SE;
    19.  
    20.             Debug.Log(direction.Angle());
    21.  
    22.             for (int c = 0, d = 1; c < ringCells - 1; c++, i++, d++) {
    23.                 cells[i] = Instantiate(cellPrefab, transform, false);
    24.                 cells[i].transform.localPosition = centers[i] =
    25.                     centers[i - 1] + Quaternion.AngleAxis(direction.Degree(), Vector3.up) *
    26.                     Vector3.forward * HexMetrics.centerDistance;
    27.  
    28.                 cells[i].SetCorners();
    29.                 yield return new WaitForSeconds(0.2f / ring);
    30.                 if (d == ring) {
    31.                     direction = direction.Next();
    32.                     d = 0;
    33.                 }
    34.             }
    35.         }
    36.     }
    37.  
    HexDirection.Degree simply being the direction times 60.

    Below, some images showing how unaligned it was before (with each cell being a differed color, thanks to the debugging tip by PraetorBlue.




    (unaligned centers)


    (aligned centers)