Instantiate as child, of child, of child...

Hey,

I’m trying to make sprite based vines, i have the main part that is a 32 x 32 pixel sprite and i’m trying to instantiate other parts on start.

When the player destroys a part, the parts below it will have to get destroyed as well, so i imagine having each parts as a child of the previous part would make this easy to manage.

Is there a way to instantiate other parts from the main part, and have them be children of the lowest children in the hierarchy?

Something like this:

85525-vine.jpg

Any suggestions would be appreciated.

You have to store the Instantiated vine into a variable. Then Instantiate like this

previousVine = Instantiate(vinePrefab, previousVine);

This will parent the new vine to the previous vine.

EDIT:
I liked the idea so I wrote up a more powerful, more optimized version. Go ahead and feel free to use it for whatever purposes :slight_smile:

using UnityEngine;
using System.Collections;

// Growth Spawner, by - Robin Trantham
// VOID.Tools - http://voidpad.wordpress.com/
// CC 3.0
public class growthSpawner : MonoBehaviour
{
    /// <summary>
    /// The object last spawned in the growth chain.
    /// </summary>
    GameObject lastSpawnedObject;
    /// <summary>
    /// The offset position that each growth should have from the parent.
    /// </summary>
    public Vector3 spawnOffset;
    /// <summary>
    /// The amount of times that a growth should occur.
    /// </summary>
    public int growthCount;
    /// <summary>
    /// The time between growths.
    /// </summary>
    public float waitTime;
    /// <summary>
    /// The actual count of the growths.
    /// </summary>
    private int Count;
    /// <summary>
    /// The Count of the Growths.
    /// </summary>
    private int count
        {
        get { return Count; }
        set
        {
            if (value >= growthCount)
            {
                resetAll();
            }
            else
                Count = value;
        }
    }
    /// <summary>
    /// The object that will be grown. CANNOT be the gameobject this is attached to.
    /// </summary>
    public GameObject objectToSpawn;
    void OnEnable()
    {
        if (objectToSpawn != gameObject && objectToSpawn != null) //Prevent infinite loops by not allowing the object to spawn itself.
        {
            count = 0; //Set the initial count to zero in-case this was stopped outside the script.
            StartCoroutine(beginGrowth()); //Start our growth process.
        }
    }
    /// <summary>
    /// Reset the growth process, and stop it. To restart the process do "StartCoroutine(beginGrowth());".
    /// </summary>
    public void resetAll()
    {
        StopAllCoroutines(); //Stop all Coroutines from this script.
        count = 0; //Set the growth count back to 0, in case we want to start over.
        lastSpawnedObject = null; //Set the last spawned object to null, so that when we start over, it will be from the beginning.
    }
    /// <summary>
    /// Grow the object based on the parameters.
    /// </summary>
    /// <returns></returns>
    IEnumerator beginGrowth()
    {
        while (count < growthCount) //As long as our growths do not equal our target goal.
        {
            yield return new WaitForSeconds(waitTime); //Make the Coroutine wait the first round.
            if (lastSpawnedObject != null) //If we started growing yet.
            {
                GameObject vineSector = (GameObject)Instantiate(objectToSpawn, lastSpawnedObject.transform); //Instantiate our growth object, childed to our last object.
                Vector3 newPosition = vineSector.transform.parent.position; //Get the position of the parent.
                newPosition += spawnOffset; //Offset the position based on our defined offset.
                vineSector.transform.position = newPosition; //Set the new object to our new offset position.
                lastSpawnedObject = vineSector; //Set our new object to be our last object, so the next object can child to it.
            }
            else //If this is our first time growing.
            {
                lastSpawnedObject = (GameObject)Instantiate(objectToSpawn, gameObject.transform); //Instantiate the new object as a child of our main parent object.
                Vector3 newPosition = gameObject.transform.position; //Get the position of our parent object.
                newPosition += spawnOffset; //Offset the position by our defined offset.
                lastSpawnedObject.transform.position = newPosition; //Set the position to the new object.
            }
            count++; //Increase the number of grown objects.
        }
    }
}

If every object only has one children, then a simple loop should suffice, I would think.

Transform currentT = topTransform;
bool lastChild = false;

while(lastChild == false){
// if the the object you are inspecting has a child, make that child the object you are inspecting
	if(currentT.childCount > 0){
		currentT = currentT.GetChild(0);
	}
// if it does not have a child, set the lastChild flag to true
// and instantiate the vine object, with the last inspected object as a parent
	else if(currentT.childCount == 0){
	lastChild = true;
	GameObject newVine = (GameObject) Instantiate(vineSprite);
	newVine.SetParent(currentT);
	}
}

Now just set the parent of the new instantiated vine to the currentT.

If there would be more than one child object inside you might want to tag every vine with a certain tag, so when searching for the next transform, you wouldn’t just straight up use GetChild(0) and check if the tag was there and such.

Example, if every single vine part is tagged “Vine”:

   Transform currentT = topTransform;
   bool lastChild = false;
    
    while(lastChild == false){
	// if the the object you are inspecting has at least one child
    	if(currentT.childCount > 0){
		// loop through all the children that is has
		for( int i = 0; i < currentT.childCount; i++){
			// and if the child has a tag "Vine" make that the current inspected object
			if(currentT.GetChild(i).CompareTag("Vine")){
				currentT = currentT.GetChild(i);
			}
		}
		}
	// if it does not have a single child, set the lastChild flag to true
	// and instantiate the vine object, with the last inspected object as a parent
    	else if(currentT.childCount == 0){
   		lastChild = true;
		GameObject newVine = (GameObject) Instantiate(vineSprite);
		newVine.SetParent(currentT);
    	}
    }