如何基于选中GameObject在Scene/Inspector视图创建动态Snap Settings按钮
实现随选中GameObject动态切换的Snap Settings按钮
我完全懂手动切换Snap Settings有多麻烦,尤其是每个对象还要对应不同的预设。下面给你一套简单的Unity解决方案,能让你在Inspector和Scene视图里都能看到当前选中对象专属的Snap按钮,一键切换配置。
步骤1:创建对象专属的Snap配置组件
首先我们需要一个组件,用来存储每个GameObject对应的3种Snap预设。把下面的脚本存为ObjectSnapConfig.cs:
using UnityEngine; [DisallowMultipleComponent] public class ObjectSnapConfig : MonoBehaviour { // 每个对象绑定3种Snap预设 public SnapPreset[] snapPresets = new SnapPreset[3]; // 定义单个Snap预设的结构 [System.Serializable] public class SnapPreset { public string presetName = "Snap Preset"; public Vector3 moveSnap = Vector3.one; public Vector3 rotateSnap = new Vector3(15, 15, 15); public Vector3 scaleSnap = Vector3.one; } }
把这个组件挂到你的3个目标GameObject上,然后在Inspector里给每个对象配置3组不同的Snap参数(比如移动步长、旋转角度、缩放比例),自定义好预设名称方便识别。
步骤2:编写自定义编辑器实现动态按钮
接下来写一个编辑器脚本,用来绘制动态按钮,并监听选中对象的变化。把下面的脚本存为ObjectSnapConfigEditor.cs,放在Editor文件夹下(没有就新建一个):
using UnityEditor; using UnityEngine; [CustomEditor(typeof(ObjectSnapConfig))] public class ObjectSnapConfigEditor : Editor { private ObjectSnapConfig targetConfig; private void OnEnable() { targetConfig = (ObjectSnapConfig)target; // 监听选中对象变化,实时更新按钮显示 Selection.selectionChanged += RefreshUI; } private void OnDisable() { Selection.selectionChanged -= RefreshUI; } private void RefreshUI() { Repaint(); SceneView.RepaintAll(); } // 扩展Inspector面板,显示Snap按钮 public override void OnInspectorGUI() { // 先显示默认的配置字段 DrawDefaultInspector(); EditorGUILayout.Space(); EditorGUILayout.LabelField("快速Snap切换", EditorStyles.boldLabel); // 遍历当前对象的3种预设,绘制按钮 for (int i = 0; i < targetConfig.snapPresets.Length; i++) { var preset = targetConfig.snapPresets[i]; if (GUILayout.Button(preset.presetName)) { ApplySnapPreset(preset); } } } // 在Scene视图绘制悬浮按钮(选中对象时显示) [DrawGizmo(GizmoType.Selected)] static void DrawSceneSnapButtons(ObjectSnapConfig config, GizmoType gizmoType) { if (!Selection.Contains(config.gameObject)) return; // 在Scene视图右上角绘制按钮区域 Handles.BeginGUI(); GUILayout.BeginArea(new Rect(10, 10, 220, 160)); GUILayout.Label($"[{config.gameObject.name}] Snap预设", EditorStyles.boldLabel); foreach (var preset in config.snapPresets) { if (GUILayout.Button(preset.presetName)) { ApplySnapPreset(preset); } } GUILayout.EndArea(); Handles.EndGUI(); } // 统一应用Snap预设到Unity编辑器 private static void ApplySnapPreset(ObjectSnapConfig.SnapPreset preset) { // 修改Unity全局的Snap配置(存在EditorPrefs里) EditorPrefs.SetFloat("MoveSnapX", preset.moveSnap.x); EditorPrefs.SetFloat("MoveSnapY", preset.moveSnap.y); EditorPrefs.SetFloat("MoveSnapZ", preset.moveSnap.z); EditorPrefs.SetFloat("RotateSnapX", preset.rotateSnap.x); EditorPrefs.SetFloat("RotateSnapY", preset.rotateSnap.y); EditorPrefs.SetFloat("RotateSnapZ", preset.rotateSnap.z); EditorPrefs.SetFloat("ScaleSnapX", preset.scaleSnap.x); EditorPrefs.SetFloat("ScaleSnapY", preset.scaleSnap.y); EditorPrefs.SetFloat("ScaleSnapZ", preset.scaleSnap.z); // 刷新Scene视图,让Snap设置立即生效 SceneView.RepaintAll(); } }
使用方式
- 给每个需要自定义Snap的GameObject挂上
ObjectSnapConfig组件,配置好3组专属的Snap参数; - 选中任意一个配置过的对象:
- 在Inspector面板底部会看到对应的3个Snap切换按钮;
- 在Scene视图的右上角也会弹出悬浮按钮区域,显示当前对象的预设;
- 点击按钮就能一键切换到该对象对应的Snap设置,完全不需要手动去调编辑器的Snap面板。
这个方案的好处是完全跟随选中对象动态更新,只会显示当前选中对象的专属Snap按钮,完美解决你手动切换的繁琐问题。
内容的提问来源于stack exchange,提问作者OnlyCodeMatters
相关产品推荐
相关产品推荐

