Unity UIElements自定义编辑器:修改网格宽高后无法自动重绘网格
解决Unity UIElements网格编辑器自动重绘问题
要解决修改网格宽高后Inspector不自动更新的问题,无需切换到IMGUI,只需通过监听属性变化并动态更新网格元素即可。核心逻辑是:CreateInspectorGUI仅在Inspector初始化时执行一次,因此需要在网格尺寸属性改变时,手动重新生成网格并替换原有元素。
修改后的完整代码
using UnityEditor; using UnityEditor.UIElements; using UnityEngine.UIElements; [CustomEditor(typeof(GridHolder))] [CanEditMultipleObjects] public class Grid_Inspector : Editor { SerializedProperty m_Grid_Width; SerializedProperty m_Grid_Height; SerializedProperty m_Grid_Size_X; SerializedProperty m_Grid_Size_Y; // 保存网格容器引用,用于后续更新 private VisualElement m_GridContainer; private void OnEnable() { m_Grid_Width = serializedObject.FindProperty("gridWidth"); m_Grid_Height = serializedObject.FindProperty("gridHeight"); m_Grid_Size_X = serializedObject.FindProperty("gridXSize"); m_Grid_Size_Y = serializedObject.FindProperty("gridYSize"); } public override VisualElement CreateInspectorGUI() { VisualElement container = new VisualElement(); Label title = new Label("Grid Inspector Element"); container.Add(title); // 网格尺寸设置区域 VisualElement gridDimensions = new VisualElement(); gridDimensions.style.flexDirection = FlexDirection.Row; PropertyField gridWidth = new PropertyField(m_Grid_Width, "Grid Dimensions (X,Y):"); PropertyField gridHeight = new PropertyField(m_Grid_Height); // 监听宽高属性变化,触发网格更新 gridDimensions.TrackPropertyValue(m_Grid_Width, _ => UpdateGrid()); gridDimensions.TrackPropertyValue(m_Grid_Height, _ => UpdateGrid()); gridDimensions.Add(gridWidth); gridDimensions.Add(gridHeight); container.Add(gridDimensions); // 网格单元尺寸设置区域 VisualElement gridElementSize = new VisualElement(); gridElementSize.style.flexDirection = FlexDirection.Row; PropertyField gridXSize = new PropertyField(m_Grid_Size_X, "Grid Size (in meters):"); PropertyField gridYSize = new PropertyField(m_Grid_Size_Y); gridElementSize.Add(gridXSize); gridElementSize.Add(gridYSize); container.Add(gridElementSize); // 初始化网格容器并添加到Inspector m_GridContainer = DrawGrid(); container.Add(m_GridContainer); return container; } private VisualElement CreateButton(string text, int sizeX, int sizeY) { Button b = new Button() { text = text }; b.style.width = new Length(sizeX, LengthUnit.Pixel); b.style.height = new Length(sizeY, LengthUnit.Pixel); return b; } private VisualElement DrawGrid() { VisualElement container = new VisualElement(); try { // 应用序列化对象修改,确保获取最新属性值 serializedObject.ApplyModifiedProperties(); for(int i = 0; i < m_Grid_Height.intValue; i++) { VisualElement row = new VisualElement(); row.style.flexDirection = FlexDirection.Row; for(int j = 0; j < m_Grid_Width.intValue; j++) { // TODO: 替换为GridHolder中的bool数组值 string text = true ? " " : "X"; row.Add(CreateButton(text, 50, 50)); } container.Add(row); } } catch(System.Exception e) { UnityEngine.Debug.LogWarning(e.Message); } return container; } // 更新网格的方法 private void UpdateGrid() { // 移除旧网格容器 m_GridContainer.parent.Remove(m_GridContainer); // 生成新网格并重新添加到Inspector m_GridContainer = DrawGrid(); m_GridContainer.parent.Add(m_GridContainer); } }
关键改动说明
- 保存网格容器引用:新增
m_GridContainer成员变量,记录当前显示的网格元素容器,方便后续替换。 - 监听属性变化:为
m_Grid_Width和m_Grid_Height添加TrackPropertyValue监听,当属性值改变时自动调用UpdateGrid方法。 - 动态更新网格:
UpdateGrid方法负责移除旧网格、重新生成新网格并添加回Inspector,实现实时更新效果。 - 确保属性值最新:在
DrawGrid中先调用serializedObject.ApplyModifiedProperties(),保证获取到用户修改后的最新宽高值。
内容的提问来源于stack exchange,提问作者Jacob D
相关产品推荐
相关产品推荐

