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

Question Alternate positions on child gameobject

Discussion in 'Scripting' started by capocchione, Feb 24, 2021.

  1. capocchione

    capocchione

    Joined:
    Dec 9, 2019
    Posts:
    47
    I have a script that generates a super simple mesh (a quad with a texture) and places it on a sphere.
    The script meshgenerator is this one:

    Code (CSharp):
    1. [RequireComponent(typeof(MeshFilter))]
    2. public class LeafMeshGenerator : MonoBehaviour
    3. {
    4.     Mesh mesh;
    5.  
    6.  
    7.     Vector3[] vertices;
    8.     Vector2[] uv;
    9.     int[] triangles;
    10.  
    11.     private void Start()
    12.     {
    13.         mesh = new Mesh();
    14.         GetComponent<MeshFilter>().mesh = mesh;
    15.  
    16.         //Material leafMaterial = new Material(Shader.Find("Standard"));
    17.         //leafMaterial.SetColor("_Color", new Color(0f, 0.7f, 0f)); //green main color
    18.  
    19.         CreateShape();
    20.         UpdateMesh();
    21.     }
    22.  
    23.     void CreateShape()
    24.     {
    25.         vertices = new Vector3[]
    26.         {
    27.             new Vector3(0,0,0),
    28.             new Vector3(0,0,.2f),
    29.             new Vector3(.2f,0,0),
    30.             new Vector3(.2f,0,.2f)
    31.         };
    32.  
    33.         uv = new Vector2[]
    34.         {
    35.             new Vector2(1f,0f),
    36.             new Vector2(1f,1f),
    37.             new Vector2(0f,0f),
    38.             new Vector2(0f,1f)
    39.         };
    40.  
    41.         triangles = new int[]
    42.         {
    43.             0,1,2,
    44.             1,3,2
    45.         };
    46.  
    47.     }
    48.  
    49.     void UpdateMesh()
    50.     {
    51.         mesh.Clear();
    52.  
    53.         mesh.vertices = vertices;
    54.         mesh.uv = uv;
    55.         mesh.triangles = triangles;
    56.  
    57.         mesh.RecalculateNormals();
    58.  
    59.     }
    60. }
    At a certain moment, a sphere is generated and during this generation, the mesh created with the script above is instantiated at position (see line 6):

    Code (CSharp):
    1.         if (!geometry && !tree.skeletonOnly)
    2.         {
    3.             geometry = GameObject.Instantiate(tree.budPrefab);
    4.             geometry.transform.position = transform.position;
    5.             geometry.transform.parent = transform;
    6.             leaf = GameObject.Instantiate(tree.leafPreFab, geometry.transform.position, Quaternion.Euler(new Vector3(0, 0, 0)));
    7.             leaf.transform.position = geometry.transform.position;
    8.             leaf.transform.parent = transform;
    9.         }


    After some iterations, I have a bunch of spheres with generated mesh attached:



    I want to "alternate" the position of generated mesh along all consecutive spheres (children).
    It should look like these (I've manually moved the generated meshes for visualization purpose):



    I was thinking about something that "remembers" where the mesh is placed on previous sphere in hierarchy.

    Thank you
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,769
    Easiest is just a bool.

    Code (csharp):
    1. // first one could be left or right, randomly
    2. bool onTheRight = Random.value < 0.5f;
    3.  
    4. // every time you place a leaf... flip it!
    5. while(inside_my_leafmaking_loop)
    6. {
    7.    ... make the leaf
    8.    if (onTheRight)
    9.    {
    10.       .. emplace it on the right
    11.    }
    12.    else
    13.    {
    14.       .. emplace it on the left
    15.    }
    16.    onTheRight = !onTheRight;
    17. }
     
    capocchione likes this.
  3. capocchione

    capocchione

    Joined:
    Dec 9, 2019
    Posts:
    47
    Thanks for the answer, the fact is that the sequence of positions is not random. If a leaf is on the right, the leaf on the subsequent child must be on the left, then on the right again, and so on. Using a random value, there is a chance that two subsequent leaves are placed both on the right or on the left, right?
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,769
    Nice bamboo btw... another thing you can do is randomly pick left/right every time.

    Also, perhaps you could consider not only left/right but a range of angles around the base stem, say from -200 to +200 degrees. In that case just use Random.Range() to create an angle, then rotate the leaf around the +Y:

    Code (csharp):
    1. float angle = Random.Range( -200, 200);
    // change the THIRD argument in your instantiate call to contain:

    Code (csharp):
    1. Quaternion.Euler(new Vector3(0, angle, 0)
     
    capocchione likes this.
  5. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,769
    Ah that original code is only for the FIRST position; you can force it to true or false if you always want the first one reliably on one side.

    The flip left/right is this code:
    onTheRight = !onTheRight;
     
    capocchione likes this.
  6. capocchione

    capocchione

    Joined:
    Dec 9, 2019
    Posts:
    47
    I see another "issue" here:
    I have no leafmaking_loop so I don't have a while loop
    The leaf is instantiated once when something happens and "attached" to the sphere, see:

    Code (CSharp):
    1.         if (!geometry && !tree.skeletonOnly)
    2.         {
    3.             geometry = GameObject.Instantiate(tree.budPrefab);
    4.             geometry.transform.position = transform.position;
    5.             geometry.transform.parent = transform;
    6.             leaf = GameObject.Instantiate(tree.leafPreFab, geometry.transform.position, Quaternion.Euler(new Vector3(0, 0, 0)));
    7.             leaf.transform.position = geometry.transform.position;
    8.             leaf.transform.parent = transform;
    9.         }
    That's why I was talking about to check where the leaf is instantiated on the "previous" sphere in hierarchy and avoid instantiate the leaf in the same position
     
  7. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,769
    Somewhere you have a place you can store state that lasts for the duration of building the tree.

    That's where to store the state.

    Somewhere you make a leaf.

    That's where to respect the bool, and then to flip the bool.
     
    capocchione likes this.