- Home /
Placing objects on a grid
EDIT: I found out how to do this much faster with Lovrenc's version of placing the objects on a grid. So, if you want an efficient way on how to place objects on a grid, look at his answer below!
Hello!
I have a grid in my project that has about 4000 single cubes in it. I have a script that lets the user, when they press "Q" or "E", move the grid UP on the Y axis. This is my movegrid script:
//current grid level
static var gridLevel : int = 0;
var grid : GameObject;
var designgui : GameObject;
var maxlevel : int = 20;
var minlevel : int = 0;
private var camlev : int = 22;
function Start()
{
gridLevel = 0;
}
function Update () {
if( gameMode.gameMode == "design" ){
if(Builder.gridbuild){
grid.SetActive(true);
if (Input.GetKeyDown("e")){
if(gridLevel < maxlevel){
gridLevel += (1);
grid.transform.position = Vector3(0,gridLevel,0);
Camera.main.transform.position.y = (camlev + gridLevel);
}
}
if (Input.GetKeyDown("q")){
if(gridLevel > minlevel){
gridLevel -= (1);
grid.transform.position = Vector3(0,gridLevel,0);
Camera.main.transform.position.y = (camlev + gridLevel);
}
}
}
}
if( gameMode.gameMode == "play" ){
grid.SetActive(false); }
if(Builder.mcbuild){
grid.SetActive(false);
}
}
But it goes REALLY slow every time it goes up and also freezes the game for a bit while it is doing so.
Is there any way to make this go faster?
Well, how else would i be able to make a grid, and make instantiated objects snap to it? This is the only way i though of doing it...
I would have done it with a big plane with a tiled texture, but i dont know how i would be able to snap the placed items to the grid
You need this grid just for snapping and you used 3000+ cubes? that is more than 36000 polygons and a lot of shifting.
Just use plane with a texture and calculate coordinates. All you need is your step (width/height).
Answer by Lovrenc · Jan 11, 2013 at 09:57 PM
Here is how i would do it.
Create a plane and set texture on it so it will represent your grid well (you said you want cell to be 1m x 1m). Then cast ray, and if it hits plane do this
.
First you get your hit postition from raycast (raycastHit.point). Then
plane.transform.position
gives you pivot point of the plane. In unity this is in the middle of the plane (drawn in orange).
You want a vector from pivot to raycast hit.
Vector3 pivotToPoint = raycastHit.point - plane.transform.position;
Now you have to calculate where to position your object:
float tileZ = pivotToPoint.Z / cellWidth;
This kinda gives us our location on z axis, but not quite. It tells us (in float) how many tiles from pivot our ray stroke (in float). We have to round that walue. Look at the image. If ray stroke more than 1.5 tiles width away, we should in fact move 2 tiles in that direction. So:
tileZ= Mathf.Round(tileZ);
You have to do the same for the X axis. Then we just have to calculate our world positions. We do this from pivot of the plane and our tile positions.
On the picture our pivot is inside the middle tile. This is important as otherwise we also have to calculate offsets.
Lets calculate final z position:
float worldZ = plane.transform.position.Z + tileZ * tileWidth;
My longest post ever. Hopefully this is somewhat correct.
You can say i am not an artist aye? :)
Really glad to see this worked. I wasn't sure my logic is correct.
Cheers!
That drawing is the essential proof that you have a future as a programmer! It's our curse, our burden, we shall SUC$$anonymous$$ at art! haha
Nice explanation mate, you showed interest in helping!
for the explanation and drawing.. this site needs many more answers+questions like this.
@bionicnacho You could edit the title of the question to something like "placing objects on a grid", so others can find it in the future more easily.
Answer by jogo13 · Jan 11, 2013 at 08:21 PM
Create a 'grid manager' script that updates them all at once, using a for loop. In addition if you have a TON of duplicate gameobjects try to avoid having scripts attached to them that have a function Update()
This is called automatically on each frame and can slow things down. You can give them a differently named cube_update()
or something like that and have the 'grid manager' call it when updated the cubes.
for(int i=0; i < cubes.Length; i++)
{
//handle key press movement
cubes.cube_update();
}
well, the script is attatched to one single ScriptContainer gameObject and what it does is moves all of a gameobject's children (all the grid blocks) up or down... So i dont have the script on every single cube