UnityEditor编辑窗口

博客链接指向相关内容,虽未展示具体信息,但标签为UnityEditor,推测围绕该编辑器展开,可能涉及使用技巧、功能介绍等信息技术领域中游戏开发方面的内容。
<think> 我们正在处理Unity Editor的自定义编辑窗口,用户想要显示字典的键值对。根据引用内容,特别是引用[1]中提到了使用SerializedProperty来处理自定义属性,包括嵌套属性(如"myCustom.i"和"myCustom.f")。对于字典,Unity本身不能直接序列化字典,但我们可以通过一些方法来实现。 在Unity中,如果要序列化字典,通常需要创建一个可序列化的类来包装键值对,然后使用一个列表来存储这些键值对,并在编辑器代码中将其显示为字典的形式。 步骤: 1. 定义可序列化的键值对类,例如: [System.Serializable] public class KeyValuePair<TKey, TValue> { public TKey Key; public TValue Value; } 2. 然后定义一个类来存储键值对列表,例如: [System.Serializable] public class SerializableDictionary<TKey, TValue> { public List<KeyValuePair<TKey, TValue>> list = new List<KeyValuePair<TKey, TValue>>(); } 3. 在MonoBehaviour中使用这个SerializableDictionary。 4. 在自定义编辑器中,我们需要遍历这个列表,并显示每个键值对。 然而,从引用[1]中,我们看到了使用SerializedProperty和SerializedObject来访问嵌套属性。因此,我们可以使用类似的方法来访问列表中的每个元素的键和值。 具体到自定义编辑器代码: - 获取到SerializedProperty,表示这个字典(实际上是列表)的属性。 - 然后使用property.arraySize获取元素数量。 - 遍历每个元素,使用GetArrayElementAtIndex(index)获取每个元素的SerializedProperty。 - 对于每个元素,再分别获取它的"Key"和"Value"属性。 注意:由于Unity的序列化系统不支持泛型,所以我们需要为每种键值对类型创建具体的类,或者使用非泛型的键值对类(使用object类型也不支持序列化)。因此,通常我们使用具体的类型,或者使用字符串作为键,值则使用具体的类型(如int, float, string等)或Unity可序列化的类型。 另外,在Unity 2019.1及以上版本,Unity提供了一个SerializedDictionary的解决方案(通过包),但这里我们假设用户使用的是较低版本或者我们自行实现。 下面是一个示例代码: 目标MonoBehaviour脚本(例如:MyDictionaryBehaviour.cs): ```csharp using System.Collections.Generic; using UnityEngine; public class MyDictionaryBehaviour : MonoBehaviour { [SerializeField] private SerializableDictionary<string, int> myDictionary = new SerializableDictionary<string, int>(); // 其他代码... } [System.Serializable] public class KeyValuePair<TKey, TValue> { public TKey Key; public TValue Value; } [System.Serializable] public class SerializableDictionary<TKey, TValue> { public List<KeyValuePair<TKey, TValue>> list = new List<KeyValuePair<TKey, TValue>>(); } ``` 自定义编辑器脚本(例如:MyDictionaryBehaviourEditor.cs): ```csharp using UnityEditor; using UnityEngine; [CustomEditor(typeof(MyDictionaryBehaviour))] public class MyDictionaryBehaviourEditor : Editor { private SerializedProperty dictionaryProp; // 指向SerializableDictionary的list属性 private void OnEnable() { // 注意:这里我们序列化的是SerializableDictionary类的list字段 dictionaryProp = serializedObject.FindProperty("myDictionary.list"); } public override void OnInspectorGUI() { serializedObject.Update(); // 显示字典内容 EditorGUILayout.LabelField("字典内容:"); if (dictionaryProp != null) { for (int i = 0; i < dictionaryProp.arraySize; i++) { SerializedProperty element = dictionaryProp.GetArrayElementAtIndex(i); SerializedProperty keyProp = element.FindPropertyRelative("Key"); SerializedProperty valueProp = element.FindPropertyRelative("Value"); EditorGUILayout.BeginHorizontal(); // 显示键和值 EditorGUILayout.PropertyField(keyProp, GUIContent.none); EditorGUILayout.PropertyField(valueProp, GUIContent.none); // 添加删除按钮 if (GUILayout.Button("删除")) { dictionaryProp.DeleteArrayElementAtIndex(i); break; // 删除后跳出当前循环,因为数组大小已经改变 } EditorGUILayout.EndHorizontal(); } } // 添加新键值对的按钮 if (GUILayout.Button("添加新条目")) { // 添加一个空元素 dictionaryProp.arraySize++; // 初始化新元素的键和值(如果需要可以设置默认值) SerializedProperty newElement = dictionaryProp.GetArrayElementAtIndex(dictionaryProp.arraySize - 1); SerializedProperty keyProp = newElement.FindPropertyRelative("Key"); SerializedProperty valueProp = newElement.FindPropertyRelative("Value"); // 设置默认值,例如空字符串和0 keyProp.stringValue = ""; valueProp.intValue = 0; } serializedObject.ApplyModifiedProperties(); } } ``` 注意:上述代码中,我们假设键是字符串类型,值是整数类型。如果键值类型不同,需要调整PropertyField的使用,因为PropertyField可以自动根据类型显示。如果键值类型不是Unity直接支持的(比如自定义的枚举或结构),可能需要特殊处理。 另外,我们为每个键值对添加了一个删除按钮,并且在添加新条目时初始化了默认值(这里键为空字符串,值为0)。你可以根据实际情况调整。 以上方法是在Inspector中显示字典的一种常用方式。如果是在自定义窗口EditorWindow)中,原理类似,只是需要使用SerializedObject和SerializedProperty来绑定目标对象的序列化属性。 另外,引用[3]提到了通过脚本动态修改属性,这里我们也是通过序列化属性来修改,所以是安全的。 如果字典的键值对类型是多种多样的,可能需要更通用的解决方案,但基本思路不变。 因此,对于用户的问题“如何在UnityEditor自定义窗口上显示字典键值对”,我们可以采用上述方法。 </think> 在Unity Editor中显示字典键值对,需要通过自定义编辑器代码结合序列化属性(SerializedProperty)实现。以下是具体方法和代码示例: ### 核心步骤 1. **创建可序列化的字典结构** Unity无法直接序列化`Dictionary<TKey, TValue>`,需使用`List<KeyValuePair>`替代 ```csharp [System.Serializable] public class SerializableDictionary<TKey, TValue> { public List<SerializablePair> items = new List<SerializablePair>(); } [System.Serializable] public class SerializablePair { public string key; public int value; // 值类型可替换 } ``` 2. **在编辑器脚本中处理序列化属性** ```csharp using UnityEditor; using UnityEngine; [CustomEditor(typeof(YourComponent))] public class DictionaryEditor : Editor { private SerializedProperty dictionaryProp; void OnEnable() { dictionaryProp = serializedObject.FindProperty("dictionary.items"); } public override void OnInspectorGUI() { serializedObject.Update(); // 显示字典内容 EditorGUILayout.LabelField("字典内容"); for (int i = 0; i < dictionaryProp.arraySize; i++) { SerializedProperty item = dictionaryProp.GetArrayElementAtIndex(i); SerializedProperty keyProp = item.FindPropertyRelative("key"); SerializedProperty valueProp = item.FindPropertyRelative("value"); EditorGUILayout.BeginHorizontal(); EditorGUILayout.PropertyField(keyProp, GUIContent.none); EditorGUILayout.PropertyField(valueProp, GUIContent.none); if (GUILayout.Button("删除", GUILayout.Width(60))) { dictionaryProp.DeleteArrayElementAtIndex(i); } EditorGUILayout.EndHorizontal(); } // 添加新条目按钮 if (GUILayout.Button("添加新条目")) { dictionaryProp.arraySize++; } serializedObject.ApplyModifiedProperties(); } } ``` ### 关键说明 1. **序列化原理**: - 使用`SerializedObject.FindProperty`获取字典属性引用[^1] - 通过`GetArrayElementAtIndex`访问列表元素 - 使用`FindPropertyRelative`读取嵌套属性(key/value)[^1] 2. **编辑器交互**: - `serializedObject.Update()`:刷新数据 - `PropertyField`自动匹配类型显示字段 - `ApplyModifiedProperties()`:应用修改[^1] 3. **自定义窗口扩展**: 若需在EditorWindow显示,需手动创建SerializedObject: ```csharp SerializedObject so = new SerializedObject(targetObject); SerializedProperty dictProp = so.FindProperty("dictionary.items"); ``` ### 优化建议 1. **添加键值验证**: ```csharp // 在添加新条目时初始化默认值 void AddNewItem() { int newIndex = dictionaryProp.arraySize; dictionaryProp.arraySize++; SerializedProperty newItem = dictionaryProp.GetArrayElementAtIndex(newIndex); newItem.FindPropertyRelative("key").stringValue = "NewKey"; newItem.FindPropertyRelative("value").intValue = 0; } ``` 2. **支持多类型值**: 使用`SerializedProperty`的`managedReferenceValue`支持多态: ```csharp [SerializeReference] public object value; ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值