如何根据所述数组的长度重命名数组中的元素? (在 Unity 检查器中)
How to rename elements in an array based on the length of said array? (In the Unity Inspector)
我正在尝试创建程序动画引擎。因为我使用叉积来计算 body 的方向,腿在数组中需要按特定顺序排列。
我想确保它对任何使用它的人来说都是直观的,所以理想情况下,我希望它根据数组的长度重命名检查器中的元素。
示例:
ideal example
这种东西是通过实现一个CustomEditor
or also a CustomPropertyDrawer
实现的
让我们举个例子说你的 class 看起来像
public class DynamicLegList : MonoBehaviour
{
public LegStepper[] Legs;
}
然后你就可以实现你通过
展示的东西
// Since the UnityEditor namespace is completely stripped of during the build process
// this should be placed in a folder called "Editor"
// or if using Assemblies this should be placed in a separate Assembly which
// is excluded from any platform except the UnityEditor itself
[CustomEditor(typeof(DynamicLegList))]
internal class DynamicLegListEditor : Editor
{
private SerializedProperty legs;
private void OnEnable()
{
legs = serializedObject.FindProperty(nameof(DynamicLegList.Legs));
}
private readonly Dictionary<int, Dictionary<int, string>> legNames = new Dictionary<int, Dictionary<int, string>>
{
{
2, new Dictionary<int, string>()
{
{0, "RightLeg"},
{1, "LeftLeg"},
}
},
{
4, new Dictionary<int, string>()
{
{0, "FrontRightLeg"},
{1, "FrontLeftLeg"},
{2, "BackRightLeg"},
{3, "BackLeftLeg"}
}
}
};
private int count;
public override void OnInspectorGUI()
{
DrawScriptField();
serializedObject.Update();
legs.isExpanded = EditorGUILayout.Foldout(legs.isExpanded, legs.displayName, true);
if (legs.isExpanded)
{
EditorGUI.indentLevel++;
{
EditorGUI.BeginChangeCheck();
{
count = EditorGUILayout.IntField("Size", legs.arraySize);
}
if (EditorGUI.EndChangeCheck())
{
if (count == 1 || legNames.ContainsKey(count))
{
legs.arraySize = count;
}
}
if (legs.arraySize == 1)
{
var leg = legs.GetArrayElementAtIndex(0);
EditorGUILayout.PropertyField(leg, new GUIContent("Leg"));
}
else
{
if (legNames.TryGetValue(legs.arraySize, out var names))
{
for (var i = 0; i < legs.arraySize; i++)
{
var leg = legs.GetArrayElementAtIndex(i);
EditorGUILayout.PropertyField(leg, new GUIContent(names[i]));
}
}
}
}
EditorGUI.indentLevel--;
}
serializedObject.ApplyModifiedProperties();
}
private void DrawScriptField()
{
EditorGUI.BeginDisabledGroup(true);
{
EditorGUILayout.ObjectField("Script", MonoScript.FromMonoBehaviour((DynamicLegList) target), typeof(DynamicLegList), false);
}
EditorGUI.EndDisabledGroup();
}
}
结果:
我正在尝试创建程序动画引擎。因为我使用叉积来计算 body 的方向,腿在数组中需要按特定顺序排列。
我想确保它对任何使用它的人来说都是直观的,所以理想情况下,我希望它根据数组的长度重命名检查器中的元素。
示例: ideal example
这种东西是通过实现一个CustomEditor
or also a CustomPropertyDrawer
让我们举个例子说你的 class 看起来像
public class DynamicLegList : MonoBehaviour
{
public LegStepper[] Legs;
}
然后你就可以实现你通过
展示的东西// Since the UnityEditor namespace is completely stripped of during the build process
// this should be placed in a folder called "Editor"
// or if using Assemblies this should be placed in a separate Assembly which
// is excluded from any platform except the UnityEditor itself
[CustomEditor(typeof(DynamicLegList))]
internal class DynamicLegListEditor : Editor
{
private SerializedProperty legs;
private void OnEnable()
{
legs = serializedObject.FindProperty(nameof(DynamicLegList.Legs));
}
private readonly Dictionary<int, Dictionary<int, string>> legNames = new Dictionary<int, Dictionary<int, string>>
{
{
2, new Dictionary<int, string>()
{
{0, "RightLeg"},
{1, "LeftLeg"},
}
},
{
4, new Dictionary<int, string>()
{
{0, "FrontRightLeg"},
{1, "FrontLeftLeg"},
{2, "BackRightLeg"},
{3, "BackLeftLeg"}
}
}
};
private int count;
public override void OnInspectorGUI()
{
DrawScriptField();
serializedObject.Update();
legs.isExpanded = EditorGUILayout.Foldout(legs.isExpanded, legs.displayName, true);
if (legs.isExpanded)
{
EditorGUI.indentLevel++;
{
EditorGUI.BeginChangeCheck();
{
count = EditorGUILayout.IntField("Size", legs.arraySize);
}
if (EditorGUI.EndChangeCheck())
{
if (count == 1 || legNames.ContainsKey(count))
{
legs.arraySize = count;
}
}
if (legs.arraySize == 1)
{
var leg = legs.GetArrayElementAtIndex(0);
EditorGUILayout.PropertyField(leg, new GUIContent("Leg"));
}
else
{
if (legNames.TryGetValue(legs.arraySize, out var names))
{
for (var i = 0; i < legs.arraySize; i++)
{
var leg = legs.GetArrayElementAtIndex(i);
EditorGUILayout.PropertyField(leg, new GUIContent(names[i]));
}
}
}
}
EditorGUI.indentLevel--;
}
serializedObject.ApplyModifiedProperties();
}
private void DrawScriptField()
{
EditorGUI.BeginDisabledGroup(true);
{
EditorGUILayout.ObjectField("Script", MonoScript.FromMonoBehaviour((DynamicLegList) target), typeof(DynamicLegList), false);
}
EditorGUI.EndDisabledGroup();
}
}
结果: