Unity EditorWindow滚动条过窄、数组标题随内容滚动问题求解

问题解决方法
两个核心问题的修复逻辑如下:
- 固定数组父标题:不要把整个数组的PropertyField放进滚动视图,先单独绘制数组的父标题(含折叠、数组大小调整控件),只把数组的元素列表放到滚动区域内,滚动时就只会移动元素,标题保持固定
- 滚动视图宽度异常:之前宽度设置失效是因为外层套了无参数的
BeginHorizontal,水平布局会默认按内容最小宽度适配,把多余的水平布局去掉,滚动视图宽度用GUILayout.ExpandWidth(true)配合窗口宽度适配,就不会出现设置宽度反而偏移的问题。

修正后完整代码
using System.Collections; using System.Collections.Generic; using UnityEditor; using UnityEngine; public class RenameSelected : EditorWindow { private static readonly Vector2Int size = new Vector2Int(500, 500); private string childrenPrefix; private int startIndex; private SerializedObject _serializedObject; public GameObject[] objects; private Vector2 scrollPos; private SerializedProperty objectsProperty; [MenuItem("GameObject/Rename Selected")] public static void ShowWindow() { EditorWindow window = GetWindow<RenameSelected>(); window.minSize = size; window.maxSize = size; } private void OnSelectionChange() { objects = Selection.gameObjects; } private void OnEnable() { _serializedObject = new SerializedObject(this); objectsProperty = _serializedObject.FindProperty("objects"); objects = Selection.gameObjects; } private void OnGUI() { childrenPrefix = EditorGUILayout.TextField("Children prefix", childrenPrefix); startIndex = EditorGUILayout.IntField("Start index", startIndex); _serializedObject.Update(); // 单独绘制固定的数组父标题,支持折叠、数组大小修改 EditorGUILayout.PropertyField(objectsProperty, new GUIContent("Objects"), false); // 只有数组展开的时候才绘制滚动区域和内部元素 if (objectsProperty.isExpanded) { EditorGUI.indentLevel++; // 滚动区域设置固定高度,宽度自动适配窗口,不会偏移 scrollPos = EditorGUILayout.BeginScrollView(scrollPos, GUILayout.Height(300), GUILayout.ExpandWidth(true)); for (int i = 0; i < objectsProperty.arraySize; i++) { SerializedProperty element = objectsProperty.GetArrayElementAtIndex(i); EditorGUILayout.PropertyField(element, new GUIContent($"Object {i}"), true); } EditorGUILayout.EndScrollView(); EditorGUI.indentLevel--; } _serializedObject.ApplyModifiedProperties(); GUILayout.Space(10); if (GUILayout.Button("Rename children")) { for (int objectI = 0; objectI < objects.Length; objectI++) { Transform selectedObjectT = objects[objectI].transform; for (int childI = 0, i = startIndex; childI < selectedObjectT.childCount; childI++) { selectedObjectT.GetChild(childI).name = $"{childrenPrefix}{i++}"; } } } } }
代码说明
- 调用
EditorGUILayout.PropertyField传includeChildren:false参数,只会绘制数组的父级标题栏,包含原生的折叠箭头、数组大小输入框、对象引用拖拽槽,和默认绘制的数组标题完全一致 - 判断
isExpanded状态,只有用户展开数组时才绘制内部的滚动列表,折叠时自动隐藏元素区域,符合Unity编辑器原生交互逻辑 - 滚动视图去掉了多余的水平布局包裹,用
GUILayout.ExpandWidth(true)让宽度自动撑满可用区域,不会出现之前设置宽度反而偏移的问题,滚动区域高度可以按需调整数值 - 增加了
EditorGUI.indentLevel的缩进调整,数组元素和父标题的层级缩进和原生Inspector保持一致 - 补上了
_serializedObject.ApplyModifiedProperties(),确保序列化数据修改能正确保存,不会出现数组拖拽赋值后刷新丢失的问题
内容的提问来源于stack exchange,提问作者Daniel Lip
相关产品推荐
相关产品推荐

