加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

【风宇冲】编辑器拓展二:序列化与编辑器

(2014-09-17 20:04:45)
分类: Unity3d之代码功能

原创文章如需转载请注明:转载自风宇冲博客

                                  
                            序列化编辑器

本文需要对C#的特性概念有一定了解。有关特性见另外一篇博客:Attribute特性。
[一]概念
Serialize:序列化,使绑定于游戏对象上的脚本中的可序列化数据可以保存,以及在编辑器中编辑。

Serializable data:可序列化数据,所有如整形字符串枚举等基本数据都是可序列化数据。类和struct需要使用Serializable声明序列化。


PS:
(1)局限
但用此方法序列化的对象不可以置null,深度也有限,
有这些需求还是用Json等数据序列化方式来储存。
(2)Json
Json可以用Unity官方的JsonUtility
或者第三方库,如JsonFx.Json.dll,但是第三方Json或者Protobuf并不能序列化Unity的数据格式,例如Vector3。因此需要自己写个XXVector3类来序列化,里面存3个float,有两个函数和Unity的Vector3互相转换即可
Json可以存字典Dictionary,但key必须是字符串,不能是int等其他东西
[二]相关特性
Serializable:
声明class或者struct为序列化数据。它在JS里是隐式实现的,但是在C#需要自己实现。
例如
[System.Serializable]
public class Item
{
public string name;
public int num;
}

SerializeField:
所有public的可序列化数据都是自动序列化的。而Private的则需要在变量前附加SerializeField特性来序列化。例如。
[SerializeField]
private float myScale;

CustomEditor:
某类的自定义Inspector显示文件。例如
[CustomEditor(typeof(类名))]
public class 任意名: Editor {
public override void OnInspectorGUI()
{
   base.OnInspectorGUI();
}
}
CanEditMultipleObjects:
可编辑多个物体,附着在类前。一般和CustomEditor一同使用。

[三]序列化与编辑器拓展
在Unity中序列化的变量类等都可以通过下述方法,快速实现在编辑器中的显示与编辑。

public override void OnInspectorGUI()
{
//得到其中的序列化类person
SerializedProperty s_person = serializedObject.FindProperty("person");
//通过PropertyField在编辑器中显示
EditorGUILayout.PropertyField(s_person);
//保存变化后的值
serializedObject.ApplyModifiedProperties();
}

[四]实例
实例1:
  1. using UnityEngine;
  2. using System.Collections;

  3. [System.Serializable]
  4. public class Person
  5. {
  6. public string name;
  7. public int age;
  8. }

  9. public class MyClass : MonoBehaviour {
  10. public Person[] person;
  11. [SerializeField]
  12. private float myScale;
  13. }
MyClassInspector.cs
  1. using UnityEngine;
  2. using System.Collections;
  3. using UnityEditor;

  4. [CustomEditor(typeof(MyClass))]
  5. public class MyClassInspector : Editor {
  6. void OnInspectorGUI()
  7. {
  8. SerializedProperty s_person = serializedObject.FindProperty("person");
  9. EditorGUILayout.PropertyField(s_person);

  10. SerializedProperty s_myScale = serializedObject.FindProperty("myScale");
  11. EditorGUILayout.PropertyField(s_myScale);

  12. serializedObject.ApplyModifiedProperties();
  13. }
  14. }
可以试试看,
MyClass.cs中的第4行去掉,那么Person将不能在Inspector中编辑。
MyClass.cs中的第13行去掉,那么myScale将不能在Inspector中编辑。

实例2: 位移旋转缩放的重置功能
NGUI有在Inspector中重置位移旋转缩放的功能。下面是一个仿写的简化版。
TransformInspector.cs
  1. using UnityEngine;
  2. using System.Collections;
  3. using UnityEditor;

  4. [CanEditMultipleObjects]
  5. [CustomEditor(typeof(Transform))]
  6. public class TransformInspector : Editor {
  7. SerializedProperty mPos;
  8. SerializedProperty mScale;
  9. public override void OnInspectorGUI()
  10. {
  11. EditorGUIUtility.labelWidth = 15f;
  12. mPos = serializedObject.FindProperty("m_LocalPosition");
  13. mScale = serializedObject.FindProperty("m_LocalScale");

  14. DrawPosition();
  15. DrawRotation();
  16. DrawScale();

  17. serializedObject.ApplyModifiedProperties();
  18. }

  19. void DrawPosition ()
  20. {
  21. GUILayout.BeginHorizontal();
  22. {
  23. bool reset = GUILayout.Button("P", GUILayout.Width(20f));
  24. EditorGUILayout.LabelField("Position",GUILayout.Width(50f));
  25. EditorGUILayout.PropertyField(mPos.FindPropertyRelative("x"));
  26. EditorGUILayout.PropertyField(mPos.FindPropertyRelative("y"));
  27. EditorGUILayout.PropertyField(mPos.FindPropertyRelative("z"));
  28. if (reset) mPos.vector3Value = Vector3.zero;
  29. }
  30. GUILayout.EndHorizontal();
  31. }

  32. void DrawScale ()
  33. {
  34. GUILayout.BeginHorizontal();
  35. {
  36. bool reset = GUILayout.Button("P", GUILayout.Width(20f));
  37. EditorGUILayout.LabelField("Scale",GUILayout.Width(50f));
  38. EditorGUILayout.PropertyField(mScale.FindPropertyRelative("x"));
  39. EditorGUILayout.PropertyField(mScale.FindPropertyRelative("y"));
  40. EditorGUILayout.PropertyField(mScale.FindPropertyRelative("z"));
  41. if (reset) mScale.vector3Value = Vector3.one;
  42. }
  43. GUILayout.EndHorizontal();
  44. }

  45. void DrawRotation ()
  46. {
  47. GUILayout.BeginHorizontal();
  48. {
  49. bool reset = GUILayout.Button("P", GUILayout.Width(20f));
  50. EditorGUILayout.LabelField("Rotation",GUILayout.Width(50f));
  51. Vector3 ls = (serializedObject.targetObject as Transform).localEulerAngles;
  52. FloatField("X",ref ls.x);
  53. FloatField("Y",ref ls.y);
  54. FloatField("Z",ref ls.z);
  55. if (reset)
  56. (serializedObject.targetObject as Transform).localEulerAngles = Vector3.zero;
  57. else
  58. (serializedObject.targetObject as Transform).localEulerAngles = ls;
  59. }
  60. GUILayout.EndHorizontal();
  61. }

  62. void FloatField(string name,ref float f)
  63. {
  64. f = EditorGUILayout.FloatField(name,f);
  65. }
  66. }

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有