- Home /
Snap object to grid
hi guys.
i've made a grid by creating a plane and set grid texture on it,besides I had a script for drag-and-drop object.
Now, i trying to create a script that when i release the mouse, the object i've been dragging snaps to the line of grid (in the picture shown below, the red is object). Can anyone help me? thanks in advance !
//Drag-and-Drop script
using UnityEngine;
using System.Collections;
public class MovePoint2 : MonoBehaviour
{
private Vector3 screenPoint;
private Vector3 offset;
void OnMouseDown()
{
screenPoint = Camera.main.WorldToScreenPoint(gameObject.transform.position);
offset = gameObject.transform.position - Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPoint.z));
Screen.showCursor = false;
}
void OnMouseDrag()
{
Vector3 curScreenPoint = new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPoint.z);
Vector3 curPosition = Camera.main.ScreenToWorldPoint(curScreenPoint) + offset;
transform.position = curPosition;
}
void OnMouseUp()
{
Screen.showCursor = true;
}
}
The best approach is probably to first work out where on the plane curPosition is;
Vector3 gridPosition = grid.InverseTransformPoint( transform.position );
Then you can move that x&y to the nearest line. Which should be
gridPosition.x = $$anonymous$$athf.Floor( gridPosition.x * GridWidth ) / GridWidth;
gridPosition.y = $$anonymous$$athf.Floor( gridPosition.y * GridHeight ) / GridHeight;
GridWidth and GridHeight are the number of lines you have. If you've done the grid texture by repeating the tiling you could get that straight from the grid's material. Then move it back into world space...
transform.position = grid.TransformPoint( gridPosition );
There might be a few errors with this, (due to size of plane, center of your dragged object etc), I'll whip up a quick test project :)
thank you :D. But i wonder that i created my grid by texture,not by script,so whether your script works?
yeah it'll be fine! Just need to fetch the gridwidth/height from your texture. I'll post an answer shortly which will do most of what you need!
Answer by GrahamReeves · May 02, 2014 at 03:55 PM
Here's a function you just need to call to snap to your grid object. The grid width/height is determined from the material's tiling, (my texture is just an edge, then repeated to make a grid)
Then we manipulate the position relative to the grid (a quad in my case) so it's irrelevant how much it's scaled, and even works when rotated!
Vector3 SnapToGrid(Vector3 Position)
{
GameObject grid = GameObject.Find ("grid");
if (! grid)
return Position;
// get grid size from the texture tiling
Vector2 GridSize = grid.renderer.material.mainTextureScale;
// get position on the quad from -0.5...0.5 (regardless of scale)
Vector3 gridPosition = grid.transform.InverseTransformPoint( Position );
// scale up to a number on the grid, round the number to a whole number, then put back to local size
gridPosition.x = Mathf.Round( gridPosition.x * GridSize.x ) / GridSize.x;
gridPosition.y = Mathf.Round( gridPosition.y * GridSize.y ) / GridSize.y;
// don't go out of bounds
gridPosition.x = Mathf.Min ( 0.5f, Mathf.Max (-0.5f, gridPosition.x) );
gridPosition.y = Mathf.Min ( 0.5f, Mathf.Max (-0.5f, gridPosition.y) );
Position = grid.transform.TransformPoint( gridPosition );
return Position;
}
Then change OnMouseDrag to include this to snap-as-you-drag
transform.position = SnapToGrid(curPosition);
or when you let go, in OnMouseUp...
transform.position = SnapToGrid(transform.position);
My example is just a square, but you just need to change the square so the center is the top of your line, or make a small adjustment to the final Postion = line
you are genius :D. Thank you very much. I regret that i don't have enough 15 reputation to vote for you :D
no need! please accept the answer if that's everything you need though! :)
@GrahamReeves the problem is, i want object snaps to the line of grid, ins$$anonymous$$d of intersection of lines of grid. Can you help me?
The snap is the center of the object (this). So what you need to do is adjust Position
to accommodate this so that Position is offset by the distance from the center to the top of this (the line).
// extents is half the size of the bounding box (in world space, so do this AFTER TransformPoint())
// https://docs.unity3d.com/Documentation/ScriptReference/Bounds.html
Position.y -= this.renderer.bounds.extents.y;
return Position;
Obviously this isn't enough if your grid is rotated, but hopefully this is enough for your needs :)
thank you :D. I will add this script to make it work :D
Your answer
Follow this Question
Related Questions
Gameobject follow mouse on center 1 Answer
Snap object to grid with offset? 1 Answer
How can I snap to hex tile centers in world x,z coords? 1 Answer
RTS building snap to grid 2 Answers
Snap All Axes Hotkey? 0 Answers