I have some objects I’m spawning, but they need to spawn locked to a grid.
This might not be a significant problem, as I can use mathf.Round to round an attempted location to its nearest whole number. However, the grid I need to snap to may be offset. Usually it will be offset by exactly one half, eg, I need to snap to 0.5, 1.5, and 2.5.
(I doubt I will need to snap to anything other than a half-unit offset, but by the time I can get this resolved I’ll likely have a system that can be easily adapted to any kind of offset.)
I really don’t know how to do this, at least, not without making a complex series of if/then statements. Does anyone have any better ideas?
I’ve done snapping by just using modulo operator (%) to get the remainder of a division of the snap interval, and then either subtracting the difference from its position, or adding the difference if it’s more than halfway.
Don’t have the code available to me right now, but it was probably something along these lines:
public static float SnapFloat(float value, float interval)
{
float rem = value % interval;
float halfInterval = interval / 2f;
if (rem > halfInterval)
{
float remDif = interval - rem;
value += remDif;
}
else
{
value -= rem;
}
return value;
}
Scenario: Object is placed at 1.652.
Nearest grid coordinate: 1.5
Rounding changes coordinate to 2.0, adding offset changes coordinate to 2.5
End result: placed at 2.5
This wouldn’t quite work either. I think it woks for making snapping points that are fractions of a whole number, but I still snap to a whole number, just offset by a given value. Since this code evaluates against half the interval size, it doesn’t properly check larger values.
Your code is for INTERVALS, I’m looking for an OFFSET. My interval is still 1.0, but to an offset value.
If my offset were 0.25, then an x position of 3.72 would need to snap to 3.25, and 3.78 would need to snap to 4.25.
This is what I’ve worked out so far, but this version only works with the offset being either zero or 0.5.
It starts getting complicated to use this method with an offset that puts the “middle range” past 1.0 or below 0.
Maybe I’ll just go with this and force my game to never need an offset other than 0.5. Apologies to anyone searching the archives for the solution to this problem.
I did my rounding wrong; dang it. I checked for a quarter on either side; I thought that was what I wanted since it equaled one half, but that’s not right.
This works for snapping to an offset of 0.5, but not to any arbitrary offset.
If the offset is 0.2, then a value of x.8 or higher needs to be have offset-plus-one added to it.
3.82 would snap to 4.2, not 3.2
Then it’s a two stage approach. First you calculate the snapped offset position based on the objects current position (so round down + offset), then you work out the difference to this position and work out where to snap from there (whether it be down or up).
It’s just linear algebra. Your interval and offset essentially define a non-rotated coordinate space. So you first bring your coordinate / value into local space, round it and transform it back.
So for example Snap(someVal, 1.6f,0.2f) would produce values like
-1.4, 0.2, 1.8, 3.4, 5, …
Since in “local space” the actual grid coordinates are whole numbers (-1, 0,1,2,3, …) when rounding you would always round correctly in between those grid points.