Search Unity

Question space GameObjects by more than one unit

Discussion in 'Scripting' started by julien83franceschi, Mar 30, 2023.

  1. julien83franceschi

    julien83franceschi

    Joined:
    Nov 14, 2020
    Posts:
    235
    Hi all,

    I would like to space out several prefabs (GameObject array: GameObject [] prefabs) by a constant space.

    -Here is my code:
    Code (CSharp):
    1.     void Start()
    2.     {
    3.  
    4.         float prefabSize = 0;
    5.         if (prefabs.Length > 0)
    6.         {
    7.             Renderer renderer = prefabs[0].GetComponent<Renderer>();
    8.             if (renderer != null)
    9.             {
    10.                 prefabSize = renderer.bounds.size.x;
    11.             }
    12.         }
    13.  
    14.         int numPrefabs = prefabs.Length;
    15.         float totalWidth = numPrefabs * prefabSize + (numPrefabs - 1) * spacing;
    16.         float startX = startPosition.x - totalWidth / 2 + prefabs.Length / 2 + spacing;
    17.  
    18.         for (int i = 0; i < numPrefabs; i++)
    19.         {
    20.             Vector3 position = new Vector3(startX + i * (prefabSize + spacing), startPosition.y, startPosition.z);
    21.             Instantiate(prefabs[i], position, Quaternion.identity);
    22.         }
    23.     }
    -and this is what it looks like:

    As you can see the left capsule is not spaced with the rectangle (composed of 4 cubes).
    Problems occur when GameObjects are bigger than a cube.

    Here are some illustrations that tell it better:

    and


    Thanks for correcting my code,

    A+
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,745
    You need to obtain size data for each item.

    Then instead of simply multiplying by a spacing, you must both add the spacing AND the size value for each object.

    I would suggest just putting a Dimensions.cs file on each object that indicates its dimensional space.

    There are other more automated ways (read all the verts, or rely on the renderer bounds), but making your own explicit Dimensions script to store this data is likely to be the easiest in the long term, the simplest to make it work since you will control 100% of the process.
     
    Bunny83 likes this.
  3. julien83franceschi

    julien83franceschi

    Joined:
    Nov 14, 2020
    Posts:
    235
    Hi everyone,

    I reviewed my code and this is what it looks like:
    Code (CSharp):
    1. void Start()
    2. {
    3.     numPrefabs = prefabsToPosition.Length;
    4.     float totalPrefabSize = 0;
    5.     Renderer firstRenderer = null;
    6.  
    7.     // Calcul de la taille totale des prefabs
    8.     for (int i = 0; i < numPrefabs; i++)
    9.     {
    10.         if (numPrefabs > 0)
    11.         {
    12.             firstRenderer = prefabsToPosition[i].GetComponent<Renderer>();
    13.             if (firstRenderer != null)
    14.             {
    15.                 totalPrefabSize += firstRenderer.bounds.size.x;
    16.             }
    17.         }
    18.     }
    19.  
    20.     // Calcul de la position de départ
    21.     float halfNumPrefabs = (numPrefabs - 1) / 2f;
    22.     float totalWidthOfPrefabs = numPrefabs * totalPrefabSize + halfNumPrefabs * spacing;
    23.     float startX = startPosition.x - totalWidthOfPrefabs / 2f;
    24.  
    25.     // Positionnement des prefabs
    26.     for (int j = 0; j < numPrefabs; j++)
    27.     {
    28.         Vector3 position = new Vector3(startX + j * (totalPrefabSize + spacing), startPosition.y, startPosition.z);
    29.         Instantiate(prefabsToPosition[j], position, Quaternion.identity);
    30.     }
    31. }
    This spaces the capsule and rectangle well by one unit.

    The problem is with the prefabs that follow.

    Indeed the rectangle and the pentamino U are spaced of 3 units, and the pentamino U and the cube are spaced of 2 units.

    See the image below:


    Also I can't get the Prefab Size sub-menu in the Inspector tab to work.

    I create as many elements as in the Prefabs To Position sub-menu.

    Then I put a 4 to element 1 (the rectangle), but it doesn't change anything.

    My question is how to space the different GameObjects with the same distance with code (see above)?


    if you can correct my code,

    you are welcome.

    A+
     
    Last edited: Mar 31, 2023
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,745
    The answer hasn't changed. Specifically:

    If you insist on putting that all in code, then do so.

    Code (csharp):
    1. float size = 1; //default
    2. if (isCube) size = 1;
    3. if (isPentomino) size = 4;
    4. if (isUShape) size = 3;
    And now use
    size
    in your computation of spacing.

    Beware also that items have "pivots" or "centers" and you can either:

    - change them in the prefabs
    - change them in the models
    - write even MORE code to compute the offsets
     
  5. julien83franceschi

    julien83franceschi

    Joined:
    Nov 14, 2020
    Posts:
    235
    Thank you for your help,

    Do I have to put this code

    Code (CSharp):
    1. float size = 1;
    2. if (isCube) size = 1;
    3. if (isPentomino) size = 4;
    4. if (isUShape) size = 3;
    instead of this one:

    Code (CSharp):
    1. { for (int i = 0; i < numPrefabs; i++)
    2.     {
    3.         if (numPrefabs > 0)
    4.         {
    5.             firstRenderer = prefabsToPosition[i].GetComponent<Renderer>();
    6.             if (firstRenderer != null)
    7.             {
    8.                 totalPrefabSize += firstRenderer.bounds.size.x;
    9.             }
    10.         }
    11.     }
    Also, do I need to create 3 variables (isCube, isPentamino and isUShape).

    We can even simplify the code by removing the variable halfNumPrefabs
    and revise the following formula:
    Code (CSharp):
    1.  float totalWidthOfPrefabs = numPrefabs * totalPrefabSize;
    Here is the new coded simplified:
    Code (CSharp):
    1.    void Start()
    2.     {
    3.         numPrefabs = prefabsToPosition.Length;
    4.         float totalPrefabSize = 0;
    5.         Renderer firstRenderer = null;
    6.  
    7.         // Calcul de la taille totale des prefabs
    8.         for (int i = 0; i < numPrefabs; i++)
    9.         {
    10.             if (numPrefabs > 0)
    11.             {
    12.                 firstRenderer = prefabsToPosition[i].GetComponent<Renderer>();
    13.                 if (firstRenderer != null)
    14.                 {
    15.                     totalPrefabSize += firstRenderer.bounds.size.x;
    16.                 }
    17.             }
    18.         }
    19.  
    20.         float startX = startPosition.x - (numPrefabs * totalPrefabSize) / 2f;
    21.  
    22.         // Positionnement des prefabs
    23.         for (int j = 0; j < numPrefabs; j++)
    24.         {
    25.             Vector3 position = new Vector3(startX + j * totalPrefabSize, 0, 0);
    26.             Instantiate(prefabsToPosition[j], position, Quaternion.identity);
    27.         }
    28.  
    29.         Debug.Log(totalPrefabSize);
    30.     }
    This gives the same result as with the code, but it doesn't space the prefabs correctly.

    Thanks for your help,

    A+
     
    Last edited: Apr 1, 2023
  6. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,745
    Because you're still doing this:

    Instead:

    - keep a running position:
    Vector3 position;


    - set it where you want the first one

    - in your iterating loop:

    ---> instantiate item at
     position


    ---> based on what shape it is, move position forward
    position += Vector3.right * size;
     
  7. julien83franceschi

    julien83franceschi

    Joined:
    Nov 14, 2020
    Posts:
    235
    I don't understand what you want to explain, I know you don't like it, but some code would be welcome.
    I just have a spacing defect with the prefabs (GameObject cube) of more than one unit (the rectangle and the pentamino U).

    Code (CSharp):
    1.     void Start()
    2.     {
    3.         numPrefabs = prefabs.Length;
    4.         float totalPrefabSize = 0;
    5.  
    6.         // Compute the total size of the prefabs
    7.         for (int i = 0; i < numPrefabs; i++)
    8.         {
    9.             Renderer prefabRenderer = prefabs.GetComponent<Renderer>();
    10.             if (prefabRenderer != null)
    11.             {
    12.                 float prefabWidth = prefabRenderer.bounds.size.x;
    13.                 totalPrefabSize += prefabWidth;
    14.                 if (i > 0)
    15.                 {
    16.                     totalPrefabSize += spacing + prefabWidth;
    17.                 }
    18.             }
    19.         }
    20.         // Compute the start position
    21.         float startX = startPosition.x - (numPrefabs * totalPrefabSize + (numPrefabs - 1) * spacing) / 2f;
    22.  
    23.         // Positioning of prefabs
    24.         for (int j = 0; j < numPrefabs; j++)
    25.         {
    26.             Vector3 position = new Vector3(startX + j * (totalPrefabSize + spacing), 0, 0);
    27.             Instantiate(prefabs[j], position, Quaternion.identity);
    28.         }
    29.     }
    Moreover I have a problem of spacing between prefabs (see image below). Indeed I use a space of 1 and in the final rendering it appears a space of 5 or 6.
    The problem is that the pentamino U is slightly off to the right and the space of prefabs is too wide.




    If you have any ideas to improve my code and formulas like startX or position,
    they are welcome,

    A+
     
    Last edited: Apr 1, 2023