Instantiate gameobject without prefab

I have an empty gameobject in my scene which contains a few child gameobjects (3d models). I want to dynamically get all the children of the parent object and I want to be able to instantiate a certain child of my choosing without having to create a prefab of each child. Does anyone know if this is posible, and if so, how? I hope I explained myself good enough. ask away if you didn’t understand :slight_smile:

What have you tried? Where are you stuck at? What tutorials did you find?

I tried to just make a foreach loop like this:

foreach(Transform child in parent)
{
    instantiate(child, gameobject.transform.position)
}

(The script is in an empty gameobject and “parent” is a reference to the gameobject that contains all the models)
something like this just to see if I it would be that simple:P which it was not. That’s really all I could think of (I’m not an expert at this stuff:P )

So really where I’m stuck at is how I can ‘copy’ one of the child objects (with the model and everything) and instantiate it at another position. I don’t want to make a prefab of each child.

I can’t remember exactly what tutorials I found but some of them mentioned something like resources.load() or something like that, but it didn’t really seem like what I needed… What I want is that I can have an empty gameobject that contains a lot of 3d-models that makes up one big model, I want to be able to get all the child objects and copy the one I want to instantiate it somewhere else (all at runtime)

hope this helped.

I free handed the code, sorry for any typo’s, this script is placed in the active parent in the scene.

public GameObject[] childrenList;

void Start()
{
    childrenList = GetComponentsInChildren<Transform>();

    int rand = Random.Range(0,childrenList.Length);
  
    GameObject newObject = new GameObject(); // creates an empty gameObject
    newObject.transform.position = new Vector3(0,0,0); //set it's position
      
    GameObject clone = (GameObject) Instantiate (childrenList[rand], new Vector3(0, 0, 0), Quaternion.identity); //create the new object
    clone.transform.parent = newObject.transform; //set the clone as a child of the empty game object
}
1 Like

this sort of works, but I have this script that generates a button for each child, and when you click on one of the buttons it pops up a window saying “you clicked on: the name of the child that you clicked on” and I want it to display that certain child together with that text… I don’t want a random child /:

How do you know which child you want to instantiate? By name or by clicking on it or something else?

I have a script on my camera which looks like this:

using UnityEngine;
using UnityEngine.UI;

public class PopUpController : MonoBehaviour
{
    public GameObject popUpCanvas;
    public Text information;
    private bool info;

    public Camera camera;

    public void Update()
    {
        RaycastHit hit;
        Ray ray = camera.ScreenPointToRay(Input.mousePosition);
      
        if (Physics.Raycast(ray, out hit) && Input.GetKeyDown(KeyCode.Mouse0))
        {
            string objectHit = hit.transform.name;

            if (info == false)
            {
                OnChildClick(objectHit);
            }

            Debug.Log(objectHit);
        }
    }

    public void OnClickButton()
    {
        popUpCanvas.SetActive(false);
        info = false;
    }

    public void OnChildClick(string partName)
    {
        information.text = "You clicked on: " + partName;
        popUpCanvas.SetActive(true);
        info = true;
    }
}

So I can either click on the child itself (which will shoot a raycast and detect what child it is and return the name) or I can click on a button (generated in another script) which when clicked calls the OnChildClick and passes in the name of the child that was clicked.

Okay, so you want to run a loop, and compare names. When you find the matching name, instantiate the new game object and set its position to… where you want.

public void OnChildClick(string objName) {
   for(int i = 0; i < parentObj.childCount; ++i) {
      Transform t = parentObj.GetChild(i);
      if(t.name == objName) {
          Transform newObj = Instantiate(t);
          newObj.position = new Vector3(10,2,0); // something here? do you pass it in to the method? I don't know
          break;
       }
   }
}

Something like, I think.

Oh, and by the way, I think you’d get a small improvement if you made the Input.GetKeyDown run first. If it’s successful, then create the raycast and so on.

using UnityEngine;
using UnityEngine.UI;
public class PopUpController : MonoBehaviour
{
    public GameObject popUpCanvas;
    public Text information;
    private bool info;
    public Camera camera;
    public void Update()
    {
        RaycastHit hit;
        Ray ray = camera.ScreenPointToRay(Input.mousePosition);
    
        if (Physics.Raycast(ray, out hit) && Input.GetKeyDown(KeyCode.Mouse0))
        {
            GameObject objectHit = hit.transform.gameObject; //changed to GameObject
            if (info == false)
            {
                OnChildClick(objectHit);
            }
            Debug.Log(objectHit.name);
        }
    }
    public void OnClickButton()
    {
        popUpCanvas.SetActive(false);
        info = false;
    }
    public void OnChildClick(GameObject partName)
    {
        GameObject newObject = new GameObject(); // creates an empty gameObject
        newObject.transform.position = new Vector3(0,0,0); //set it's position
       
        GameObject clone = (GameObject) Instantiate (partName, new Vector3(0, 0, 0), Quaternion.identity); //create the new object
        clone.transform.parent = newObject.transform; //set the clone as a child of the empty game object

        information.text = "You clicked on: " + partName.name;
        popUpCanvas.SetActive(true);
        info = true;
    }
}

I don’t see how any of this is related to the child stuff you asked for. so I didn’t include it in the code. You already have the object you want via the raycast.

I like your change (GameObject or Transform) would be nicer than a string.

The OP would just need to change the reference in the button’s inspector, too, to match the new signature. :slight_smile:

Probably just the way they were thinking about it.

You did remind me that they probably want to include a means to prevent clicking on a new copy to spawn another one, though (if that’s not desired).

I don’t think his idea is going to work this way. It looks like and sounds like he wants to click on a gameobject, enable a UI and show some text with a copy of the gameObject sitting next to the text. He would need to do something different. maybe set the gameObject to a child in the UI, but then I think about scale and RectTransform positioning.

I didn’t get that he wanted it near something… Maybe :slight_smile:
I thought he just wanted to print the name of the clicked object, spawn a copy & place it somewhere.

I guess what I was saying was, assuming that’s accurate, just to ensure that clicking anything in the game won’t duplicate it. =) Perhaps checking against a list of children from the specific parent, before running the rest of the code.

That said, if the OP can elaborate just to be sure, that wouldn’t hurt :wink: