Unity自定义ScriptableObject属性显示的三种方式
2017-05-26 20:25
871 查看
1. 继承Editor,重写OnInspectorGUI方法
Editor官方文档效果
实现
定义一个测试类TestClass,一个可序列化类DataClass[CreateAssetMenu] public class TestClass : ScriptableObject { [Range(0, 10)] public int intData; public string stringData; public List<DataClass> dataList; } [System.Serializable] public class DataClass { [Range(0, 100)] public int id; public Vector3 position; public List<int> list; }
//指定类型 [CustomEditor(typeof(TestClass))] public class TestClassEditor : Editor { SerializedProperty intField; SerializedProperty stringField; void OnEnable() { //获取指定字段 intField = serializedObject.FindProperty("intData"); stringField = serializedObject.FindProperty("stringData"); } public override void OnInspectorGUI() { // Update the serializedProperty - always do this in the beginning of OnInspectorGUI. serializedObject.Update(); EditorGUILayout.IntSlider(intField, 0, 100, new GUIContent("initData")); EditorGUILayout.BeginHorizontal(); EditorGUILayout.PropertyField(stringField); if(GUILayout.Button("Select")) { stringField.stringValue = EditorUtility.OpenFilePanel("", Application.dataPath, ""); } EditorGUILayout.EndHorizontal(); // Apply changes to the serializedProperty - always do this in the end of OnInspectorGUI. //需要在OnInspectorGUI之前修改属性,否则无法修改值 serializedObject.ApplyModifiedProperties(); base.OnInspectorGUI(); } }
Editor嵌套
通过Edtiro.CreateEditor可实现Editor的嵌套。创建一个类TestClass2,它包含一个TestClass的属性。
[CreateAssetMenu] public class TestClass2 : ScriptableObject { public TestClass data; }
创建一个Test2Class的asset。它的Inspector面板的默认显示:
它并没有把TestClass的属性显示出来,如果要查看TestClass的属性,必须双击,跳到相应界面,但这样有看不到TestClass2的属性。
如果想在Test2Class的Inspector面板中直接看到并且可以修改TestClass的属性,可以重写TestClass2的Editor,并在其中嵌套TestClass的Editor。
[CustomEditor(typeof(TestClass2))] public class TestClass2Editor : Editor { Editor cacheEditor; public override void OnInspectorGUI() { // Update the serializedProperty - always do this in the beginning of OnInspectorGUI. serializedObject.Update(); //显示TestClass2的默认UI base.OnInspectorGUI(); GUILayout.Space(20); var data = ( (TestClass2)target ).data; if(data != null) { //创建TestClass的Editor if (cacheEditor == null) cacheEditor = Editor.CreateEditor(data); GUILayout.Label("this is TestClass2"); cacheEditor.OnInspectorGUI(); } } }
这样就可以直接在TestClass2的面板中直接查看和编辑TestClass的属性。
2. 使用PropertyDrawer
PropertyDrawer官方文档如果想修改某种特定类型的显示,使用继承Editor的方式就会变得很麻烦,因为所有使用特定类型的asset都需要去实现一个自定义的Editor,效率非常低。这种情况就可以通过继承PropertyDrawer的方式,对指定类型的属性,进行统一显示。
效果
为Inspector面板中的所有string属性添加一个选择文件按钮,选中文件的路径直接赋值给该变量。实现
[CustomPropertyDrawer(typeof(string))] public class StringPropertyDrawer : PropertyDrawer { public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { Rect btnRect = new Rect(position); position.width -= 60; btnRect.x += btnRect.width - 60; btnRect.width = 60; EditorGUI.BeginProperty(position, label, property); EditorGUI.PropertyField(position, property, true); if (GUI.Button(btnRect, "select")) { string path = property.stringValue; string selectStr = EditorUtility.OpenFilePanel("选择文件", path, ""); if (!string.IsNullOrEmpty(selectStr)) { property.stringValue = selectStr; } } EditorGUI.EndProperty(); } }
加了一个PropertyDrawer之后,Inspector面板中的**所有**string变量都会额外添加一个Select按钮。
注意事项
PropertyDrawer只对可序列化的类有效,非可序列化的类没法在Inspector面板中显示。OnGUI方法里只能使用GUI相关方法,不能使用Layout相关方法。
PropertyDrawer对应类型的所有属性的显示方式都会修改,例如创建一个带string属性的MonoBehaviour:
3. 使用PropertyAttribute
PropertyAttribute官方文档如果想要修改部分类的指定类型的属性的显示,直接使用PropertyDrawer就无法满足条件,这时可以结合PropertyAttribute和PropertyAttribute来实现需求。
效果
为部分指定类的int或float属性的显示添加滑动条,滑动条的上下限可根据类和属性自行设置。实现
public class RangeAttribute : PropertyAttribute { public float min; public float max; public RangeAttribute(float min, float max) { this.min = min; this.max = max; } } [CustomPropertyDrawer(typeof(RangeAttribute))] public class RangeDrawer : PropertyDrawer { // Draw the property inside the given rect public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { // First get the attribute since it contains the range for the slider RangeAttribute range = attribute as RangeAttribute; // Now draw the property as a Slider or an IntSlider based on whether it's a float or integer. if (property.propertyType == SerializedPropertyType.Float) EditorGUI.Slider(position, property, range.min, range.max, label); else if (property.propertyType == SerializedPropertyType.Integer) EditorGUI.IntSlider(position, property, (int)range.min, (int)range.max, label); else EditorGUI.LabelField(position, label.text, "Use Range with float or int."); } }
修改TestClass和DataClass
[CreateAssetMenu] public class TestClass : ScriptableObject { [Range(0, 10)] public int intData; public string stringData; public List<DataClass> dataList; } [System.Serializable] public class DataClass { [Range(0, 100)] public int id; public Vector3 position; public List<int> list; }
其他
需要修改显示的类都需要满足Unity的序列化规则这几种显示方式对Serializable Class都可以使用,并不需要一定是ScriptableObject。只是在编辑器下,ScriptableObject来保存临时数据比较常用,所以使用ScriptableObject来做例子。
demo下载
转载请注明出处:http://blog.csdn.net/wuwangxinan/article/details/72773297
相关文章推荐
- 自定义DataGrid控件显示数据的方式
- [JavaScript]自定义Title的显示方式
- [转载] 使用IValueConverter接口实现自定义绑定数据的显示方式
- ▲三种方式实现元素水平居中显示
- 三种方式实现自定义圆形页面加载中效果的进度条
- 自定义UserControl的属性为什么不能在设计时显示在属性窗口中
- 一个简单的小程序演示Unity的三种依赖注入方式
- 自定义UserControl的属性为什么不能在设计时显示在属性窗口中
- 【Visual Studio风格开发系列 - PropertyGrid控件】PropertyGrid控件中添加自定义显示方式
- GridView显示数据的三种方式(一)
- JS+DIV实现自定义Title的显示方式
- PropertyGrid控件扩展--自定义显示属性内容、属性名称及分类
- 自定义UserControl的属性为什么不能在设计时显示在属性窗口中
- 设置ListView控件的view属性为LargeIcon时的显示方式
- 位图显示的三种方式
- [JavaScript]自定义Title的显示方式
- 自定义表单的三种方式实现
- 自定义用户控件显示属性分类、描述、默认值
- Magento Block的三种显示方式
- GridView显示数据三种方式(二)