我正在开发一个 Unity 程序,其中有一个基于网格的系统。我正在尝试为网格系统制作一个自定义编辑器,基本上您可以更改网格的大小,让它显示一组代表网格的按钮,每次单击按钮时,它都会迭代一些图块。
我已经完成了大部分工作,只是当宽度/高度发生变化时,我无法让检查器重新绘制网格。如果我运行游戏,它可以运行,但不会自动运行。据我所知,调用 CreateInspectorGUI 似乎不可能发生。有没有一种方法可以在不使用 OnInspectorGUI 的情况下做到这一点?我试图留在 UIElements 系统中,但我不确定我是否有选择。
我的检查器代码如下所示:
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 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 void OnInspectorGUI()
// {
// EditorGUILayout.PropertyField(m_Grid_Width, new GUIContent("Grid Width"), GUILayout.Height(20));
// serializedObject.ApplyModifiedProperties();
// }
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, _ => {
UnityEngine.Debug.Log("Hit");
Repaint();
});
gridDimensions.Add(gridWidth);
gridDimensions.Add(gridHeight);
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(gridDimensions);
container.Add(gridElementSize);
// // randomColorButton.style.width = new Length(50, LengthUnit.Pixel);
// // randomColorButton.style.height = new Length(50, LengthUnit.Pixel);
container.Add(DrawGrid());
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
{
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 Connect this to the bool array in GridHolder
string text = true?" ":"X";
row.Add(CreateButton(text, 50, 50));
}
container.Add(row);
}
}
catch(System.Exception e)
{
UnityEngine.Debug.LogWarning(e.Message);
}
return container;
}
}
感谢您提供的任何帮助!最坏的情况是我切换到 IMGUI 系统,但我宁愿不必这样做
您必须重新创建网格,而不是仅仅调用
Repaint
。
所以你可能会做类似的事情
public override VisualElement CreateInspectorGUI()
{
...
var gridContainer = new VisualElement();
gridDimensions.TrackPropertyValue(m_Grid_Width, _ => {
UnityEngine.Debug.Log("Hit");
DrawGrid(gridContainer);
});
...
container.Add(gridContainer);
DrawGrid(gridContainer);
return container;
}
// instead of creating and returning the container rather just
// take a container as parameter and generate the grid into it
private VisualElement DrawGrid(VisualElement container)
{
// remove any previous content
container.Clear();
try
{
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 Connect this to the bool array in GridHolder
string text = true?" ":"X";
row.Add(CreateButton(text, 50, 50));
}
container.Add(row);
}
}
catch(System.Exception e)
{
UnityEngine.Debug.LogWarning(e.Message);
}
}
因此,您不必在
CreateInspectorGUI
中仅创建一次网格,而是在每次修改大小时重新创建网格,并传入要放置其的根容器。