- Home /
Instantiating Cube Prefabs with scale
How can I make the cube gameobject prefab instantiate so that they will always touch if i change the scale of the object?
Currently, the cubes are separated if i change their size. Apologies this is such a simple question:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Gameplay : MonoBehaviour
{
public Transform brick;
public int gridWidth=10;
public int gridDepth=10;
public int gridHeight=10;
// Start is called before the first frame update
void Start(){
for (int y = 0; y < gridHeight; y=y+1)
{
for (int z = 0; z < gridDepth; z=z+1)
{
for (int x = 0; x < gridWidth; x=x+1)
{
Instantiate (brick, new Vector3 (x, y, z), Quaternion.identity);
}
}
}
}
}
Essentially I want a 3d cube out of instantiated game objects cube, as many as I want through the inspector.
Thanks
Answer by DerDerErIst · Nov 26, 2020 at 01:49 AM
First You need to Define what the localsize of the Objects is:
Here is a simple Version, you have to Setup your Prefab correctly:
Make an Empty GameObject, then Add as Example a Cube to it. Make it a Prefab and Implement it in the Unity Inspector to the brickParent object.
Parent Objects should always be on Scale 1, so we gonna scale the localSize of the Child Object, scaling the Parent Objects can often causes huge problems later in development Stages.
public class UnityAnswer : MonoBehaviour
{
//Setup the Prefab correct, Empty Gameobject LocalScale 1 and the Cube (other Object) as Child Object of the Empty GameObject
public GameObject brickParent;
public int gridWidth = 10;
public int gridDepth = 10;
public int gridHeight = 10;
//Define the Size of your Objects
public float localScale = .5f;
// Start is called before the first frame update
void Start()
{
for (int y = 0; y < gridHeight; y++)
{
for (int z = 0; z < gridDepth; z++)
{
for (int x = 0; x < gridWidth; x++)
{
//We Instantiate the GameObject and the Position of x/y/z * localScale so we can Access it
GameObject go = Instantiate(brickParent, new Vector3(x * localScale, y * localScale, z * localScale), Quaternion.identity) as GameObject;
//Since we only have One Child (The Cube as Example) we get the First Child (Dont mess around with GetComponentInChildren because GetComponentInChildren doesnt really works like its Named it always will start with GetComponent and get the Parent Object
Transform t = go.transform.GetChild(0);
//We Scale the Child Object to the new localScale
t.localScale = new Vector3(localScale, localScale, localScale);
}
}
}
}
}
Here is the same Approach just with 2 additional Methods to show you how you chould Change the Grid then in Runtime
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Random = UnityEngine.Random;
public class UnityAnswer : MonoBehaviour
{
public GameObject brickParent;
public int gridWidth = 10;
public int gridDepth = 10;
public int gridHeight = 10;
public float localScale = .5f;
List<GameObject> gridObjects = new List<GameObject>();
// Start is called before the first frame update
void Start()
{
for (int y = 0; y < gridHeight; y++)
{
for (int z = 0; z < gridDepth; z++)
{
for (int x = 0; x < gridWidth; x++)
{
GameObject go = Instantiate(brickParent, new Vector3(x * localScale, y * localScale, z * localScale), Quaternion.identity) as GameObject;
Transform t = go.transform.GetChild(0);
t.localScale = new Vector3(localScale, localScale, localScale);
gridObjects.Add(go);
}
}
}
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.Alpha1))
{
RefreshLocalScale();
}
if (Input.GetKeyDown(KeyCode.Alpha2))
{
NewGrid();
}
}
private void RefreshLocalScale()
{
localScale = Random.Range(.5f,2f);
if (gridObjects.Count > 0)
{
foreach (var item in gridObjects)
{
item.transform.position = new Vector3(item.transform.position.x * localScale, item.transform.position.y * localScale, item.transform.position.y * localScale);
Transform t = item.transform.GetChild(0);
t.localScale = new Vector3(localScale, localScale, localScale);
}
}
}
private void NewGrid()
{
localScale = 1.5f;
if (gridObjects.Count > 0)
{
foreach (var item in gridObjects)
{
Destroy(item);
}
}
gridObjects.Clear();
for (int y = 0; y < gridHeight; y++)
{
for (int z = 0; z < gridDepth; z++)
{
for (int x = 0; x < gridWidth; x++)
{
GameObject go = Instantiate(brickParent, new Vector3(x * localScale, y * localScale, z * localScale), Quaternion.identity) as GameObject;
Transform t = go.transform.GetChild(0);
t.localScale = new Vector3(localScale, localScale, localScale);
gridObjects.Add(go);
}
}
}
}
}
Answer by mharris45 · Nov 26, 2020 at 12:10 AM
Why not add the cubes as a child of a Empty GameObject then just scale the empty?
This will be much faster than scaling each individually.
Thats and absolute "Easy Way" to do it, but You shouldnt do that, since it will give you weird Behaviours later in the Game when things are not scaled properly.
Answer by Rich_XR · Nov 26, 2020 at 09:14 AM
Thanks for your time on this @DerDerErIst will implement today. Thank you!
Hey @DerDerErIst this has worked! The only issue now is that it instantiates at 0,0,0 in the scene, even if i move the entire Gameobject with child cube and script into desired location?
it starts at 0 and ends at 10
you have to change your parameters if you want it at different location
the grid get build up with y/z/x on 0 increment the value by one multiplied by the scale
if you want your grid as example starting on x = 25 then you need to start your loop at 25
lets say as example:
for (int x = 25; x < (gridWidth + 25); x++)
now he will start on x 25.
dont forget to mark my answer as solved please