Is there a way to make a GameObject immovable in the editor?

Is there a way to make a GameObject immovable in the editor either by script or in the UI that I have been overlooking?
I’m thinking of the Edit Mode not the actual Gameplay.

I don’t know of something built in… but if I were to do this, I would give it a component with a Custom editor (UnityEditor.Editor) that takes control of the UnityEditor.Tools to prevent the object being manipulated: Unity - Scripting API: Tools

Note you can set them up as unselectable in the hierarchy, but I assume you want to be able to select them still.

As spiney wrote

Objects can not be selected in the scene when this is ticked. You can still select them from the Hierarchy.

Thanks for your responses. Making them unselectable is not quite what I was looking for as you can still select them from hierarchy and then move them with the move tool.

In the meantime I tested setting the GameObjects NotEditable HideFlag. This makes the object immovable but also you can’t alter the rotation or interact with the MonoBehaviours fields in the inspector any more…

Another thing I tried is checking if the GameObjects transform has changed and if so, setting the position back to zero or whatever position you want the object to remain:

void Update() {
    if (transform.hasChanged) {
        transform.position = Vector3.zero;
        transform.hasChanged = false;
    }
}

This works so that the move tool handle still appears but if you drag on it nothing happens.
However this feels a bit yucky in my opinion…

I also looked into trying it via the UnityEditor.Tools or the ToolManager as you suggested but I did not find a way to “hijack” the builtin move tool. I didn’t even accomplish to get a hold of its instance…
Maybe someone has more insight on if thats actually possible?

It’s pretty straight forward.

First make a dummy component:

using UnityEngine;

public class ImmoveableGameObject : MonoBehaviour { }

Then make a custom editor for it, that turns of the current tool while it’s viewed:

using UnityEditor;

[CanEditMultipleObjects]
[CustomEditor(typeof(ImmoveableGameObject))]
public class ImmoveableGameObjectEditor : Editor
{
    private Tool lastTool = Tool.None;

    private void OnEnable()
    {
        lastTool = Tools.current;
        Tools.current = Tool.None;
        Tools.hidden = true;
    }

    private void OnDestroy()
    {
        Tools.current = lastTool;
        Tools.hidden = false;
    }
}

Note this turns off all types of manipulations, but could easily altered to be selective.

EDIT: It also doesn’t stop its Transform component being edited, but this could also be solved in the same editor.

This is indeed pretty straight forward, I was thinking way to complicated :smile:
However I am still not totally happy with that solution…
I tried checking for the Move tool in the activeToolChanged Callback of the ToolManager and setting the active tool to Tool.None. This is not allowed though, it produces the following Exception:

InvalidOperationException: Attempting to set the active tool from EditorTool.OnActivate or EditorTool.OnDeactivate. This is not allowed.

EDIT: Obviously not allowed since it would produce an endless loop facepalm

So at the moment I am stuck with the following solution:

  • Setting the HideFlag.NotEditable on the Objects transform, so the fields of other Components on the object stay editable
  • Checking for the Move tool in the activeToolChanged Callback and hiding/showing the tools
using UnityEngine;
public class ImmoveableGameObject : MonoBehaviour {
    void Awake() {
        transform.hideFlags = HideFlags.NotEditable;
    }
}
using UnityEditor;
using UnityEditor.EditorTools;

[CanEditMultipleObjects]
[CustomEditor(typeof(ImmoveableGameObject))]
public class ImmoveableGameObjectEditor : Editor {
    private Tool lastTool = Tool.None;

    private void OnEnable() {
        lastTool = Tools.current;
        HandleToolChange();
        ToolManager.activeToolChanged += HandleToolChange;
    }

    private void OnDestroy() {
        Tools.hidden = false;
        if (Tools.current == Tool.None)
            Tools.current = lastTool;
        ToolManager.activeToolChanged -= HandleToolChange;
    }
 
    private void HandleToolChange() {
        if (Tools.current == Tool.Move) Tools.hidden = true;
        else Tools.hidden = false;
    }
}

Not really optimal…also there seems to be no clean way of preventing a single transform property from altering without also blocking the others (just the hacky solution of resetting it in each Update call)?