Unity3D 编辑器对象锁定工具
在实际的 Unity 项目里,有很多对象是运行时自动生成的、由系统维护的或者依赖复杂逻辑的。如果能随便改它们,很容易导致数据错乱、功能失效,甚至场景崩掉。所以,Unity 提供了 HideFlags 这套机制来“保护现场”。
保护对象
HideFlags.NotEditable // 不能编辑HideFlags.HideInHierarchy // 在层级里隐藏HideFlags.DontSave // 不保存到场景HideFlags.HideAndDontSave // 完全隐身+不保存
组合起来可以实现:
-
“你看不见”
-
“你看得见但不能动”
-
“运行完就消失”
示例代码
#if UNITY_EDITORusing UnityEditor;#endifusing UnityEngine;[ExecuteInEditMode]public class LockTest : MonoBehaviour{voidUpdate(){if (GameObject.Find("LockedObject") == null){GameObject obj = new GameObject("LockedObject");obj.hideFlags = HideFlags.None;// obj.hideFlags = HideFlags.NotEditable;}}}
说明:在编辑器状态(没点 Play)也会执行,每一帧都在检查,如果没有这个物体 → 就创建一个。 编辑器守护进程:
-
你删掉对象 → 下一帧给你补回来
-
你改名字 → 逻辑可能失效再生成
-
你清空场景 → 它又生成
HideFlags 到底是什么
它本质是一个位标记(bitmask),可以理解为给 GameObject 打标签,告诉 Unity:“这个东西该怎么对待”。
通用工具
using UnityEditor;using UnityEngine;public class EditableControlMenu{// =========================// 锁定选中对象(包含子物体)// =========================[MenuItem("Tools/Lock Selected %#l")] // Ctrl+Shift+LstaticvoidLockSelected(){var selection = Selection.gameObjects;if (selection.Length == 0){Debug.LogWarning("No GameObject selected.");return;}int count = 0;foreach (var obj in selection){// 避免锁 Prefab Root(重要)if (PrefabUtility.IsAnyPrefabInstanceRoot(obj)){Debug.LogWarning($"Skip Prefab Root: {obj.name}");continue;}count += ApplyToHierarchy(obj, true);}Debug.Log($"Locked {count} objects.");}// =========================// 解锁选中对象(包含子物体)// =========================[MenuItem("Tools/Unlock Selected %#u")] // Ctrl+Shift+UstaticvoidUnlockSelected(){var selection = Selection.gameObjects;if (selection.Length == 0){Debug.LogWarning("No GameObject selected.");return;}int count = 0;foreach (var obj in selection){count += ApplyToHierarchy(obj, false);}Debug.Log($"Unlocked {count} objects.");}// =========================// 一键解锁所有对象(救命按钮)// =========================[MenuItem("Tools/Force Unlock ALL")]staticvoidUnlockAll(){var all = Object.FindObjectsOfType<GameObject>(true);int count = 0;foreach (var obj in all){if (obj.hideFlags != HideFlags.None){Undo.RecordObject(obj, "Force Unlock");obj.hideFlags = HideFlags.None;EditorUtility.SetDirty(obj);count++;}}Debug.Log($"Force Unlocked {count} objects (ALL).");}// =========================// 核心逻辑:递归处理层级// =========================staticintApplyToHierarchy(GameObject root, bool lockState){int count = 0;var transforms = root.GetComponentsInChildren<Transform>(true);foreach (var t in transforms){var obj = t.gameObject;// 已经是目标状态就跳过if (lockState && obj.hideFlags == HideFlags.NotEditable)continue;if (!lockState && obj.hideFlags == HideFlags.None)continue;Undo.RecordObject(obj, lockState ? "Lock Object" : "Unlock Object");obj.hideFlags = lockState ? HideFlags.NotEditable : HideFlags.None;EditorUtility.SetDirty(obj);count++;}return count;}}

快捷键
-
Ctrl + Shift + L → 锁定对象
-
Ctrl + Shift + U → 解锁对象
注意事项
-
仅在 Unity Editor 中有效
-
不影响打包运行
-
不建议锁定 Prefab Root
-
Force Unlock 会影响所有隐藏对象,请谨慎使用
获取链接
GitHub 链接:
https://github.com/XiaoHer001/Lock/releases/download/V1.0/EditableControlMenu.unitypackage
Gitee 链接:
https://gitee.com/XiaoHer001/Lock/releases/download/V1.0/EditableControlMenu.unitypackage
飞书云文档:
https://bcnfy9fyspaa.feishu.cn/docx/UKUid6F7LoPiRfxDuWIc59C5nvd?from=from_copylink
往期热门:
夜雨聆风