Place an object snapped to grid?

Most of the objects in my world need to be placed in whole number increments; I can't place a wall with an X value of 4.006149, it has to be at 4.

I can easily move things around by holding control to snap the movement, but whenever I place an object into my scene it always appears at some artibitrary position, and then I have to go into the inspector and manually change the position in the transform. It's very annoying.

Is there some way to lock placing an object to the grid? Some way to force a prefeb a drag and drop into the scene to be placed at whole-number values?

Check the toolbar above the scene view. Make sure grid snapping is enabled and set to the desired grid size. The grid icon is highlighted when snapping is enabled.

That doesn’t actually snap the placement of a new object I drop into a scene.
It can quickly be used to move something to a whole number; quicker than manually editing it at least. But I actually need my objects snapping to half-unit increments, so I wind up having to turn it on, drop in an object, adjust its position, turn the snapping off, and holding control while I move it to the correct place.

This does improve my workflow, so thank you for that. But is there really no way to simply drop in an object and have its position already snapped?

I don’t believe there’s an out of the box solution for this, but certainly not impossible to do this yourself by hooking into the object change events system: Unity - Scripting API: ObjectChangeEvents

There’s some examples on how to do this in this thread: Editor callbacks for GameObject creation, deletion, duplication by user or user script

I‘ll test this later because I‘m certain snapping takes place regardless of whether the object is already in the scene or dragged in. Also note that you can set the grid size and snapping to any float value such as 0.125.

You are correct!

I rarely drag & drop stuff onto the scene view itself because, well, the position is NEVER what I want it to be anyway. I’m more inclined to drag it into the scene hierarchy where the object gets placed at the origin respectively what the prefab root transform indicates, then move it. But as worlds get larger then yes, you’d want to not drop the object, then pick it up again and move it in order to snap it.

Btw, I noticed if you have Grid snapping set to one value (say: 5) and Increment snapping to half of grid snapping (here: 2.5) this lets you quickly snap objects to the grid but when you need half-grid snapping you can just hold down Ctrl and drag, that’s kinda nice because I’ve fumbled with this in the past.

Anyway, I made a quick script that could certainly be improved (perhaps an editor script / EditorTool that checks the selected object(s) and determines whether grid snapping should be enabled and what the grid size will be based on info obtained from the object itself such as tags or a component).

This script goes on every prefab that MUST stay on a grid no matter what:

using UnityEngine;

[ExecuteAlways]
public class SnapToGridInEditor : MonoBehaviour
{
    [SerializeField] private Vector3 m_GridSize = new(2.5f, 0f, 2.5f);

    private void Awake()
    {
#if UNITY_EDITOR
        if (Application.isPlaying)
            Destroy(this);
#else
        Destroy(this);
#endif
    }

    private void Update()
    {
#if UNITY_EDITOR
        if (Application.isPlaying == false)
        {
            var pos = transform.position;
            transform.position = new Vector3(
                Mathf.RoundToInt(pos.x / m_GridSize.x) * m_GridSize.x,
                Mathf.RoundToInt(pos.y / m_GridSize.y) * m_GridSize.y,
                Mathf.RoundToInt(pos.z / m_GridSize.z) * m_GridSize.z);
        }
#endif
    }
}

When you drag in a prefab with this script on the prefab root, it will instantly snap to the given grid position. I left grid.y at 0 so in that case the object will only move on the XZ plane which is handy if you work with a flat terrain.

Note: I expected a division by zero exception in (pos.y / m_GridSize.y) but that doesn’t happen. No idea why.

The snapping persists even if grid snapping in the scene view is disabled. If you don’t want the object snapping, you’d have to disable the component.

The hack-ish thing about this is that it lives on the prefab itself and modifying the script settings shows up as prefab overrides, which they are. It also adds minimal overhead as the component gets destroyed when entering playmode.

Hence the recommendation to make this an EditorTool that is game-aware and knows that any object tagged “GridSnap” or has a component of type “SnapToGrid” (empty script, or at most providing grid settings) will require the object to be grid snapped.

This could be improved even further with a toogle to have “snap to ground” available, particularly useful with terrain, or generally snapping to meshes, colliders and their surface normals for alignment. I think some of that already exists with some key combo and certainly there are tools in the store that help out there.

This spurred me on to make one, and, honestly, it was pretty simple overall.

Here it is in a gist: https://gist.github.com/spiney199/8826eaafdfc215f16c0460d2125071df

And the tool in action: https://i.gyazo.com/4c4f0ae9eb14347f54ffece78ed69115.mp4

Edit: I realise I probably didn’t need the configuration stuff, and could’ve done it all in one script and check EditorSnapSettings.gridSnapEnabled, but shrug!

2 Likes

Nice stuff!

I think there’s merit in having a better workflow for designing objects on a grid where the grid acts intelligently on what object you’re picking. I’m thinking: Walls => snap to edges. Pillars or even-sized (2x2, 4x4) objects => snap to corners. Towers or odd-sized (1x1, 3x3) => snap to cell center. Props => snap to ground, on a sub-grid, perhaps respect colliders or align to edges.

Hmmm … need to explore this further when I get back to ProTiler. It became a technical endeavour too early without the proper use-cases respectively the use-cases I saw wouldn’t fit well with a uniform, wholly filled grid (or: voxel space). Not without complicating storage and retrieval, and memory usage in general.

1 Like

Well conceivably, you may be able to manage that simply by creating your prefabs with an offset. If the center of the wall prefab is off by half a unit, it would thus snap to the edge.
But it would only work depending on how your game has to be set up and what that “grid” really is to you.