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
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
}
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.
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
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