Snap Objects to Grid during Runtime with mouse

Hello,

I want to snap objects on a premade runtime-grid. The cellsize is 16 x 16 units wide/tall.

Vector3 mousePos = Input.mousePosition;
mousePos.z = 64;
smoothPos = Camera.main.ScreenToWorldPoint(mousePos); 
if(Mathf.Abs((int)smoothPos.x) % 16 == 1) //Objectpos should be ..,-56,-40,-24,-8,8,24,40,56..
	snapPos.x = (int)smoothPos.x+7;
if(Mathf.Abs((int)smoothPos.z) % 16 == 1) //Objectpos should be ..,-56,-40,-24,-8,8,24,40,56..
	snapPos.z = (int)smoothPos.z+7;
spawnedObj.transform.position = snapPos;

It works perfect on positive smoothpos, but if smoothpos is negative, the snapping is not correct, it’s always shifted about 2 units.

Any help would be appreciated!

Casting to int has a a problem with negative values. While positive values are always casted to the nearest integer that is equal or lower than the given value, negative values are casted to the next greater value:

value    (int)value
 1.1         1
 1.9         1
-1.1        -1
-1.9        -1

So a cast will always round towards “0”. You should use one of those instead:

  • Mathf.FloorToInt
  • Mathf.CeilToInt
  • Mathf.RoundToInt

depening on your needs. For example FloorToInt will return this

value    FloorToInt(value)
 1.1           1
 1.9           1
-1.1          -2
-1.9          -2

so it’s always rounding down. CeilToInt will always round up and RoundToInt rounds up if the value is greater than 0.5 otherwise it rounds down.

Also i’m not sure why you compare to “1” and not “0”

Maybe something like this?:

// [ ... ]
int x = Mathf.FloorToInt(smoothPos.x) + 8;
int y = Mathf.FloorToInt(smoothPos.y) + 8;

if ((x % 16) == 0)
    snapPos.x = x - 8;
if ((y % 16) == 0)
    snapPos.y = y - 8;
// [ ... ]