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

How do i get all child gameobjects under gameobject and move each one in random speed ?

Discussion in 'Scripting' started by benydayag, Sep 1, 2016.

  1. benydayag

    benydayag

    Joined:
    Aug 1, 2016
    Posts:
    91
    I have 20 Spheres under empty GameObject called Spheres.

    In the Update function before i used the code to move the GameObject called Spheres to make all the child Spheres to move.

    But now i want to make that each child Sphere will move in Random speed.
    So now in the Update function i'm using the code:

    Code (csharp):
    1.  
    2. GameObject goo = GameObject.Find ("Spheres");
    3.         speed = Random.Range (1, 20);
    4.         foreach (Transform t in goo.transform)
    5.         {
    6.             t.transform.position =  Vector3.Lerp (pos1, pos2, Mathf.PingPong (Time.time * speed,1.0f));
    7.         }
    But it's moving only one Sphere and i don't see all the other 19 Spheres.


    Code (csharp):
    1.  
    2. using System;
    3. using UnityEngine;
    4. using Random = UnityEngine.Random;
    5. using System.Collections.Generic;
    6.  
    7. public class NewBehaviourScript : MonoBehaviour {
    8.  
    9.     private int SphereCount = 20;
    10.     private float SphereSize = 10.0f;
    11.  
    12.     private  Vector3 pos1 = new Vector3(-4,0,0);
    13.     private Vector3 pos2 = new Vector3(4,0,0);
    14.     public float speed = 5.0f;
    15.  
    16.     // Use this for initialization
    17.     void Start () {
    18.  
    19.         for (var i = 0; i < SphereCount; i++) {
    20.             var o = GameObject.CreatePrimitive (PrimitiveType.Sphere);
    21.             o.tag = "Sphere";
    22.             o.transform.localScale = new Vector3 (SphereSize, SphereSize, SphereSize);
    23.             o.transform.position = new Vector3 (i * 50 + 70, 1, 1);
    24.             GameObject _sphere = GameObject.Find ("Spheres");
    25.             o.transform.parent = _sphere.transform;
    26.         }
    27.  
    28.    
    29.     }
    30.    
    31.     // Update is called once per frame
    32.     void Update () {
    33.  
    34.         GameObject goo = GameObject.Find ("Spheres");
    35.         speed = Random.Range (1, 20);
    36.         foreach (Transform t in goo.transform)
    37.         {
    38.             t.transform.position =  Vector3.Lerp (pos1, pos2, Mathf.PingPong (Time.time * speed,1.0f));
    39.         }
    40.  
    41.         /*foreach (GameObject go in Resources.FindObjectsOfTypeAll(typeof(GameObject)) as GameObject[]) {
    42.  
    43.             if (go.name == "Spheres") {
    44.                 speed = Random.Range (1, 20);
    45.                 go.transform.position =  Vector3.Lerp (pos1, pos2, Mathf.PingPong (Time.time * speed,1.0f)); // Random.Range (5, 30);
    46.             }
    47.         }*/
    48.     }
    49. }
     
  2. Hyblademin

    Hyblademin

    Joined:
    Oct 14, 2013
    Posts:
    725
    Why not just attach a script to the child spheres that does this?
     
  3. benydayag

    benydayag

    Joined:
    Aug 1, 2016
    Posts:
    91
    To make another script file that will get all the child Spheres and will move them ? What should i do in the new script ? The code i tried to
     
  4. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,139
    I think what he means is create a script. Something like sphereMove. Each sphere then has this script on it. When ready to move, you can either have the movement in a coroutine or have a bool value (like startMove) that you set to true. When the value is true, in update, each sphere will move on it's own. (or you call the coroutine) If you then set the value to false, the spheres stop moving. This also helps because your spheres can respond to colliding with stuff or whatever you need them to do on their own. Same thing with movement as they each control their own movement.
     
  5. image28

    image28

    Joined:
    Jul 17, 2013
    Posts:
    457
    try t.localPosition
     
  6. takatok

    takatok

    Joined:
    Aug 18, 2016
    Posts:
    1,496
    Your problem is this: GameObject.Find only returns one object, the first Object it finds.
    IF you want to code it the way your going now, you'll need to tag your Sphere Prefab with a tag = "Spheres" so all the spheres get created with the tag "Spheres" then do this:

    Code (CSharp):
    1.  
    2. GameObject[] goos = GameObject.FindGameObjectsWithTag ("Spheres");
    3.      
    4.         foreach (GameObject oneGoo in goos)
    5.         {
    6.             speed = Random.Range (1, 20);
    7.             goo.transform.position =  Vector3.Lerp (pos1, pos2, Mathf.PingPong (Time.time * speed,1.0f));
    8.         }
     
  7. takatok

    takatok

    Joined:
    Aug 18, 2016
    Posts:
    1,496
    I just realized this code is running in Update. And in general you don't want to use GetComponents and (especially!) FindObject functions in Update. Its fairly expensive and unnnecessary.

    You should make a variable in your class
    GameObject goos[];

    Then when you create a new set of spheres call:
    GameObject[] goos =GameObject.FindGameObjectsWithTag("Spheres");

    always make sure you update goos whenever you destroy spheres or create new ones.
    Then take that line out of your Update function. goos will always be set to the current list of spheres. This way your not finding all the spheres every update (30 times a second) since its unnecessary and will really slow down your game.
     
  8. benydayag

    benydayag

    Joined:
    Aug 1, 2016
    Posts:
    91

    In goos there is only one index. Only the GameObject called Spheres. And inside it in it's transform i see childCount 20. Then when running thegame all the 20 Spheres are moving same speed. The array goos should contain only one GameObject or all the 20 ?
     
  9. benydayag

    benydayag

    Joined:
    Aug 1, 2016
    Posts:
    91
    Yes did it already. And creating the goos array in the Start function after creating all the Spheres. In the Update function i have foreach loop. Still goos contain only one object.
     
  10. benydayag

    benydayag

    Joined:
    Aug 1, 2016
    Posts:
    91
    takatok If you could show me how the code should look like ? I tried it but it's not working in my case.
     
  11. takatok

    takatok

    Joined:
    Aug 18, 2016
    Posts:
    1,496
    I am assuming you have a GameObject with this script attached to it. That game object is creating spheres from Instantiate? If thats true do this:
    Make sure this parent object does *NOT* have a tag spheres. Then go into your spheres Prefab and make sure that Prefab is tagged Spheres.

    If that isn't the case I need to know more about what this script is attached to, and how you make spheres.
     
  12. benydayag

    benydayag

    Joined:
    Aug 1, 2016
    Posts:
    91

    This is the complete script in the Start function i create the Spheres and put them as childs under the new empty GameObject name Spheres:

    Code (csharp):
    1.  
    2. using System;
    3. using UnityEngine;
    4. using Random = UnityEngine.Random;
    5. using System.Collections.Generic;
    6.  
    7. public class NewBehaviourScript : MonoBehaviour {
    8.  
    9.     private int SphereCount = 20;
    10.     private float SphereSize = 10.0f;
    11.  
    12.     private  Vector3 pos1 = new Vector3(-4,0,0);
    13.     private Vector3 pos2 = new Vector3(4,0,0);
    14.     public float speed = 5.0f;
    15.     private GameObject[] goos;
    16.  
    17.     // Use this for initialization
    18.     void Start () {
    19.  
    20.         for (var i = 0; i < SphereCount; i++) {
    21.             var o = GameObject.CreatePrimitive (PrimitiveType.Sphere);
    22.             o.tag = "Sphere";
    23.             o.transform.localScale = new Vector3 (SphereSize, SphereSize, SphereSize);
    24.             o.transform.position = new Vector3 (i * 50 + 70, 1, 1);
    25.             GameObject _sphere = GameObject.Find ("Spheres");
    26.             o.transform.parent = _sphere.transform;
    27.         }
    28.          
    29.         goos = GameObject.FindGameObjectsWithTag ("Spheres");
    30.  
    31.     }
    32.  
    33.     // Update is called once per frame
    34.     void Update () {
    35.  
    36.         foreach (GameObject oneGoo in goos)
    37.         {
    38.             speed = Random.Range (1, 20);
    39.             oneGoo.transform.position =  Vector3.Lerp (pos1, pos2, Mathf.PingPong (Time.time * speed,1.0f));
    40.         }
    41.     }
    42. }
    So in the Hierarchy i have Terrain and empty new GameObject called Spheres.
    The 20 Spheres are childs under the GameObject Spheres.
     
  13. takatok

    takatok

    Joined:
    Aug 18, 2016
    Posts:
    1,496
    change:
    Code (CSharp):
    1. goos = GameObject.FindGameObjectsWithTag ("Spheres");
    to:
    Code (CSharp):
    1. goos = GameObject.FindGameObjectsWithTag ("Sphere");
    This first line is finding our Main Object _sphere
    We need to find all the spheres that you tagged with a "Sphere" (no 's' at the end)
     
  14. benydayag

    benydayag

    Joined:
    Aug 1, 2016
    Posts:
    91
    takatok it seems to be now fine with the tag.
    But the speed movement i wanted it to be random but it's not really working.
    What i'm getting is like accordion effect and the first Sphere is not moving at all.

    What i want is that the Spheres will move between the 4 to -4 position on the x in random speed each Sphere to be in another speed.

    This is a small very short video clip i recorded of the unity when the game is running showing the accordion effect. Not even close to what i wanted:



    This is the code now in the Update function i'm using the counting variable if not it will not make a space between the Spheres:

    Code (csharp):
    1.  
    2. using System;
    3. using UnityEngine;
    4. using Random = UnityEngine.Random;
    5. using System.Collections.Generic;
    6.  
    7. public class NewBehaviourScript : MonoBehaviour {
    8.  
    9.     private int SphereCount = 20;
    10.     private float SphereSize = 10.0f;
    11.  
    12.     private  Vector3 pos1 = new Vector3(-4,0,0);
    13.     private Vector3 pos2 = new Vector3(4,0,0);
    14.     public float speed = 5.0f;
    15.     private GameObject[] goos;
    16.  
    17.     // Use this for initialization
    18.     void Start () {
    19.  
    20.         for (var i = 0; i < SphereCount; i++) {
    21.             var o = GameObject.CreatePrimitive (PrimitiveType.Sphere);
    22.             o.tag = "Sphere";
    23.             o.transform.localScale = new Vector3 (SphereSize, SphereSize, SphereSize);
    24.             o.transform.position = new Vector3 (i * 50 + 70, 1, 1);
    25.             GameObject _sphere = GameObject.Find ("Spheres");
    26.             o.transform.parent = _sphere.transform;
    27.         }
    28.            
    29.         goos = GameObject.FindGameObjectsWithTag ("Sphere");
    30.     }
    31.  
    32.     int counting = 0;
    33.     // Update is called once per frame
    34.     void Update () {
    35.  
    36.         foreach (GameObject oneGoo in goos)
    37.         {
    38.             if (counting == goos.Length)
    39.                 counting = 0;
    40.             pos1 = new Vector3 (counting * 50 - 4, 0, 0);
    41.             speed = Random.Range (1, 10);
    42.             oneGoo.transform.position =  Vector3.Lerp (pos1, pos2, Mathf.PingPong (Time.time * speed,1.0f));
    43.            counting++;
    44.         }
    45.     }
    46. }
     
  15. takatok

    takatok

    Joined:
    Aug 18, 2016
    Posts:
    1,496
    You can try this;
    Code (CSharp):
    1.     float[] sphereSpeeds = new float[SphereCount];
    2.     bool[] sphereRight = new bool[SphereCount];
    3.     float[] initialX = new float[SphereCount];
    4.  
    5.     // In Start When you are creating spheres add this line
    6.     o.transform.position = new Vector3(i* 50 + 70, 1, 1);  // <-- this line was already there
    7.     initialX[i] = i*50+70;  // save our initial spot
    8.  
    9.     //Add this line at the end of start after finding goos
    10.     for (int i = 0; i<goos.Length;i++)
    11.     {
    12.         sphereSpeeds[i] = Random.Range(1,20);
    13.         sphereRight[i] = true;
    14.     }
    15.  
    16.     //Now in update
    17.      // delete your code and use this
    18.     for (int i = 0;i <goos.Length;i++)
    19.     {
    20.          int distance = sphereSpeed[i] * Time.deltaTime;
    21.          Vector3 pos = goos[i].transform.position;
    22.          if (sphereRight[i])
    23.          {
    24.                pos.x = pos.x + distance;
    25.                if (pos.x  > initialX[i]+4.0f)
    26.                {
    27.                    pos.x = initialX[i]+4.0f  
    28.                    sphereRight[i] = false;
    29.                 }
    30.           }
    31.           else
    32.           {
    33.                 pos.x = pos.x - distance;
    34.                if (pos.x  < initialX[i]-4.0f)
    35.                {
    36.                    pos.x = initialX[i]-4.0f  
    37.                    sphereRight[i] = true;
    38.                 }
    39.           }
    40.           goos[i].transform.position = pos;
    41.     }
    Note: Your setting your spheres 70 away to start, +50 farther back each sphere. +/- 4 might not be noticeable and you might need to increase 4
     
  16. benydayag

    benydayag

    Joined:
    Aug 1, 2016
    Posts:
    91
    takatok the random is now working but not the speed. For example i changed the random line to this Range:

    Code (csharp):
    1. sphereSpeeds[i] = Random.Range(10,20);
    And i see in the Speeds many values some 10 and 12 17 11 but when i'm running the game each Sphere is moving in another speed but very slow. No matter how many times i tried to run the game none of the sphere moved close to speed 10 or above. Looks like they are moving between 1 to 5. Strange.
     
  17. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,139
    If you're multiplying sphereSpeed with Time.deltaTime, I think the result will be slower than you think since Time.deltaTime is a small value.
     
  18. takatok

    takatok

    Joined:
    Aug 18, 2016
    Posts:
    1,496
    You have to math it out. If your moving from -4 to +4 thats 8 Units. If speed was 1 then, then we are moving 1 unit per second and it would take 8 seconds to move the entire distance. even at speed 16 it will take .5 seconds to move.

    If these things are spaced 50 units apart and you are viewing an entire line. That means you are very far away from them to see them all. So their movement will naturally seem slow. Also switching from 0,20 to 10,20 will make all of them seem to be moving even closer in speed. Try changing the random from 0,100 and making the min/max distance they move +10 to -10 instead of +4 to -4