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

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:

GameObject goo = GameObject.Find ("Spheres");
        speed = Random.Range (1, 20);
        foreach (Transform t in goo.transform) 
        {
            t.transform.position =  Vector3.Lerp (pos1, pos2, Mathf.PingPong (Time.time * speed,1.0f));
        }

But it’s moving only one Sphere and i don’t see all the other 19 Spheres.

using System;
using UnityEngine;
using Random = UnityEngine.Random;
using System.Collections.Generic;

public class NewBehaviourScript : MonoBehaviour {

    private int SphereCount = 20;
    private float SphereSize = 10.0f;

    private  Vector3 pos1 = new Vector3(-4,0,0);
    private Vector3 pos2 = new Vector3(4,0,0);
    public float speed = 5.0f;

    // Use this for initialization
    void Start () {

        for (var i = 0; i < SphereCount; i++) {
            var o = GameObject.CreatePrimitive (PrimitiveType.Sphere);
            o.tag = "Sphere";
            o.transform.localScale = new Vector3 (SphereSize, SphereSize, SphereSize);
            o.transform.position = new Vector3 (i * 50 + 70, 1, 1);
            GameObject _sphere = GameObject.Find ("Spheres");
            o.transform.parent = _sphere.transform;
        }

   
    }
   
    // Update is called once per frame
    void Update () {

        GameObject goo = GameObject.Find ("Spheres");
        speed = Random.Range (1, 20);
        foreach (Transform t in goo.transform) 
        {
            t.transform.position =  Vector3.Lerp (pos1, pos2, Mathf.PingPong (Time.time * speed,1.0f));
        }

        /*foreach (GameObject go in Resources.FindObjectsOfTypeAll(typeof(GameObject)) as GameObject[]) {

            if (go.name == "Spheres") {
                speed = Random.Range (1, 20);
                go.transform.position =  Vector3.Lerp (pos1, pos2, Mathf.PingPong (Time.time * speed,1.0f)); // Random.Range (5, 30);
            }
        }*/
    }
}

Why not just attach a script to the child spheres that does this?

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

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.

try t.localPosition

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:

GameObject[] goos = GameObject.FindGameObjectsWithTag ("Spheres");
      
        foreach (GameObject oneGoo in goos)
        {
            speed = Random.Range (1, 20);
            goo.transform.position =  Vector3.Lerp (pos1, pos2, Mathf.PingPong (Time.time * speed,1.0f));
        }

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.

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 ?

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.

takatok If you could show me how the code should look like ? I tried it but it’s not working in my case.

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.

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:

using System;
using UnityEngine;
using Random = UnityEngine.Random;
using System.Collections.Generic;

public class NewBehaviourScript : MonoBehaviour {

    private int SphereCount = 20;
    private float SphereSize = 10.0f;

    private  Vector3 pos1 = new Vector3(-4,0,0);
    private Vector3 pos2 = new Vector3(4,0,0);
    public float speed = 5.0f;
    private GameObject[] goos;

    // Use this for initialization
    void Start () {

        for (var i = 0; i < SphereCount; i++) {
            var o = GameObject.CreatePrimitive (PrimitiveType.Sphere);
            o.tag = "Sphere";
            o.transform.localScale = new Vector3 (SphereSize, SphereSize, SphereSize);
            o.transform.position = new Vector3 (i * 50 + 70, 1, 1);
            GameObject _sphere = GameObject.Find ("Spheres");
            o.transform.parent = _sphere.transform;
        }
          
        goos = GameObject.FindGameObjectsWithTag ("Spheres");

    }
  
    // Update is called once per frame
    void Update () {

        foreach (GameObject oneGoo in goos)
        {
            speed = Random.Range (1, 20);
            oneGoo.transform.position =  Vector3.Lerp (pos1, pos2, Mathf.PingPong (Time.time * speed,1.0f));
        }
    }
}

So in the Hierarchy i have Terrain and empty new GameObject called Spheres.
The 20 Spheres are childs under the GameObject Spheres.

change:

goos = GameObject.FindGameObjectsWithTag ("Spheres");

to:

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)

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:

using System;
using UnityEngine;
using Random = UnityEngine.Random;
using System.Collections.Generic;

public class NewBehaviourScript : MonoBehaviour {

    private int SphereCount = 20;
    private float SphereSize = 10.0f;

    private  Vector3 pos1 = new Vector3(-4,0,0);
    private Vector3 pos2 = new Vector3(4,0,0);
    public float speed = 5.0f;
    private GameObject[] goos;

    // Use this for initialization
    void Start () {

        for (var i = 0; i < SphereCount; i++) {
            var o = GameObject.CreatePrimitive (PrimitiveType.Sphere);
            o.tag = "Sphere";
            o.transform.localScale = new Vector3 (SphereSize, SphereSize, SphereSize);
            o.transform.position = new Vector3 (i * 50 + 70, 1, 1);
            GameObject _sphere = GameObject.Find ("Spheres");
            o.transform.parent = _sphere.transform;
        }
           
        goos = GameObject.FindGameObjectsWithTag ("Sphere");
    }

    int counting = 0;
    // Update is called once per frame
    void Update () {

        foreach (GameObject oneGoo in goos)
        {
            if (counting == goos.Length)
                counting = 0;
            pos1 = new Vector3 (counting * 50 - 4, 0, 0);
            speed = Random.Range (1, 10);
            oneGoo.transform.position =  Vector3.Lerp (pos1, pos2, Mathf.PingPong (Time.time * speed,1.0f));
           counting++;
        }
    }
}

You can try this;

    float[] sphereSpeeds = new float[SphereCount];
    bool[] sphereRight = new bool[SphereCount];
    float[] initialX = new float[SphereCount];

    // In Start When you are creating spheres add this line
    o.transform.position = new Vector3(i* 50 + 70, 1, 1);  // <-- this line was already there
    initialX[i] = i*50+70;  // save our initial spot

    //Add this line at the end of start after finding goos
    for (int i = 0; i<goos.Length;i++)
    {
        sphereSpeeds[i] = Random.Range(1,20);
        sphereRight[i] = true;
    }

    //Now in update
     // delete your code and use this
    for (int i = 0;i <goos.Length;i++)
    {
         int distance = sphereSpeed[i] * Time.deltaTime;
         Vector3 pos = goos[i].transform.position;
         if (sphereRight[i])
         {
               pos.x = pos.x + distance;
               if (pos.x  > initialX[i]+4.0f)
               {
                   pos.x = initialX[i]+4.0f  
                   sphereRight[i] = false;
                }
          }
          else
          {
                pos.x = pos.x - distance;
               if (pos.x  < initialX[i]-4.0f)
               {
                   pos.x = initialX[i]-4.0f  
                   sphereRight[i] = true;
                }
          }
          goos[i].transform.position = pos;
    }

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

takatok the random is now working but not the speed. For example i changed the random line to this Range:

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.

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.

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