How to generate unlimited nested children of objects randomly depth levels ?

The code now generate 100 objects at random positions.

What i want to is to make something like this structure :

Object 1
     Child 1
     Child 2
         Child 3
      Child 4

Object 2
     Child 1
     Child 2
     Child 3

Object 3
     Child 1
         Child 2
             Child 3
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GenerateObjects : MonoBehaviour
{
    public GameObject objectPrefab;

    [Range(1, 100)]
    public int numberOfObjects = 1;

    private GameObject parent;
    private int count = 0;

    // Start is called before the first frame update
    void Start()
    {
        parent = GameObject.Find("Generate Objects");

        StartCoroutine(SpawnObjects());
    }

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

    IEnumerator SpawnObjects()
    {
        while (true)
        {
            yield return new WaitForSeconds(0);

            if (objectPrefab != null)
            {
                GameObject go = Instantiate(objectPrefab, new Vector3(Random.Range(0,10), Random.Range(0,10), Random.Range(0,10)), Quaternion.identity,parent.transform);
                for(int i = 0; i < Random.Range(1,100); i++)
                {
                    GameObject child = Instantiate(objectPrefab, new Vector3(Random.Range(0, 10), Random.Range(0, 10), Random.Range(0, 10)), Quaternion.identity, parent.transform);
                    go.transform.SetParent(child.transform);
                }
            }

            count++;

            if(count == 100)
            {
                StopAllCoroutines();
                break;
            }

            yield return null;
        }
    }
}

The reason i’m using coroutine is to be able to control the spawning time.

I tried to add this part for the children part but it’s not working. it’s randomly create children but only one depth level and not for all the objects the random is seems to be random parents that get a child.

I want that each cloned prefab will have some children with unlimited random depths of levels.

for(int i = 0; i < Random.Range(1,100); i++)
                {
                    GameObject child = Instantiate(objectPrefab, new Vector3(Random.Range(0, 10), Random.Range(0, 10), Random.Range(0, 10)), Quaternion.identity, parent.transform);
                    go.transform.SetParent(child.transform);
                }

I think you just have this reversed ^ ^ ^ ^

If you have this:

Object1
Object2

And you want this:

Object1
    Object2

Then the call would be:

Object2.transform.SetParent( Object1.transform);

You are telling an object “This is your parent.” Passing null to .SetParent() will unparent the object.

Also if you want some other random spawning ideas, check out my MakeGeo project:

MakeGeo is presently hosted at these locations:

https://bitbucket.org/kurtdekker/makegeo

Particularly things with the word “spawn” in them.

1 Like

I think i solved it. what do you think ? it’s working.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GenerateObjects : MonoBehaviour
{
    public GameObject objectPrefab;

    [Range(1, 100)]
    public int numberOfObjects = 1;
    public int maxDepth;
    public int currentDepth;

    private GameObject parent;
    private int count = 0;

    // Start is called before the first frame update
    void Start()
    {
        parent = GameObject.Find("Generate Objects");

        StartCoroutine(SpawnObjects());
    }

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

    IEnumerator SpawnObjects()
    {
        while (true)
        {
            yield return new WaitForSeconds(0);

            if (objectPrefab != null)
            {
                GameObject go = Instantiate(objectPrefab, new Vector3(Random.Range(0,10), Random.Range(0,10), Random.Range(0,10)), Quaternion.identity,parent.transform);
                GenerateChildren(go);
            }

            count++;

            if(count == 100)
            {
                StopAllCoroutines();
                break;
            }

            yield return null;
        }
    }

    GameObject child;
    private void GenerateChildren(GameObject go)
    {
        if (currentDepth < maxDepth)
        {
            for (int i = 0; i < Random.Range(1,7); i++)
            {
                child = Instantiate(objectPrefab, new Vector3(Random.Range(0, 10), Random.Range(0, 10), Random.Range(0, 10)), Quaternion.identity);
                child.transform.parent = go.transform;
            }

            currentDepth++;
            GenerateChildren(child);
        }
        else
        {
            currentDepth = 0;
        }
    }
}

Then ship it! Me studying the code isn’t gonna change if it works or not. :slight_smile:

1 Like

I see the main issue has already be solved. However I’d like to point out that your original inner loop would have a really strange distribution since you roll a new random number each iteration.
The distribution would be
Distribution

// i     p      total p
// ...................
// 0    1.00    1.0000
// 1    0.99    0.9900
// 2    0.98    0.9702
// 3    0.97    0.9411
// 4    0.96    0.9035
// 5    0.95    0.8583
// 6    0.94    0.8068
// 7    0.93    0.7503
// 8    0.92    0.6903
// 9    0.91    0.6282
//10    0.90    0.5653
//11    0.89    0.5032 --> 50% chance
//12    0.88    0.4428
//13    0.87    0.3852
//14    0.86    0.3313
//15    0.85    0.2816
//16    0.84    0.2365
//17    0.83    0.1963
//18    0.82    0.1610
//19    0.81    0.1304
//20    0.80    0.1043 --> 10% chance
//21    0.79    0.0824
//22    0.78    0.0643
//23    0.77    0.0495
//24    0.76    0.0376
//25    0.75    0.0282
//26    0.74    0.0209
//27    0.73    0.0152
//28    0.72    0.0110 --> 1% chance
//29    0.71    0.0078
//30    0.70    0.0055
//31    0.69    0.0038
//32    0.68    0.0026
//33    0.67    0.0017
//34    0.66    0.0011
//35    0.65    0.0007
//36    0.64    0.0005
//37    0.63    0.0003
//38    0.62    0.0002
//39    0.61    0.0001
// ...
//50    0.50    10^-7
// ...
//60    0.40    10^-11
// ...
//70    0.30    10^-15
// ...
//80    0.20    10^-22
// ...
//90    0.10    10^-30
// ...
//99    0.01    10^-43

Not only is this quite inefficient to roll a new random number each iteration, what would be the intention behind it? with the limit of 100, the last elements will never be generated at all since the probability is lower than the probability that two GUIDs are equal.

As for your new range (1 to 7) the probabilities are

//0   1.0
//1   0.8333
//2   0.5556
//3   0.2778
//4   0.0926
//5   0.0154
//6   0.0
2 Likes