码迷,mamicode.com
首页 > 编程语言 > 详细

Unity 序列化 总结

时间:2015-03-16 21:06:53      阅读:904      评论:0      收藏:0      [点我收藏+]

标签:

查找了

Script Serialization

http://docs.unity3d.com/Manual/script-Serialization.html

自定义序列化及例子:

http://docs.unity3d.com/ScriptReference/ISerializationCallbackReceiver.OnBeforeSerialize.html

 和Unity 圣典

在这博友 的基础上 再总结下Unity 的序列化 

 

 

序列化的作用是: 可以显示变量(类,结构等)在inspector(检视面板)上.如图

                                                                                                                       技术分享

Unity在运行时候的能在inspector(检视面板)上看到变量(类,结构等)时候,Unity已经发生了序列化;

 

Unity序列化的关键字是 Serializable 和 SerializeField.

          Serializable: 用于 自定义的,非 abstract 的类. 结构体等 , 使这类型也能序列化

          SerializeField: 用于 非public 类型(如private),  使非public 类型也能序列化

 

脚本的字段需要满足什么条件才能被序列化?(必须同时满足)

1. public 类型,或者有 [SerializeField]

2. 不是 static

3. 不是 const

4. 不是 readonly

5. 类型必须是 Unity 可以序列化的类型

 

Unity 可以序列化哪类型?

1. 自定义的,非 abstract 的类,且有 [Serializable]

2. 有 [Serializable] 的结构体

3. UnityEngine.Object 的子类的引用

4. 原生类型(int,float,double,bool,string, etc)

5. 以上类型的数组

6. 以上类型的 List<T>

 

以下几种情况,Unity的序列化并不一定能按你的预期执行:

自定义类结构: 待理解

[Serializable]
class Animal
{
   public string name;
}

class MyScript : MonoBehaviour
{
      public Animal[] animals;
}

 

类成员里面有Null的变量: 

                            例如在序列化一个变量(类.结构等)的时候,如果这个变量里面有Null,Unity将会的实例化一个新对象,然后序列化,然后进入死循环,因为Unity的序列化在非主线程运行,所以出现这种情况会导致程序性能下降

class Test : MonoBehaviour
{
    public Trouble t;
}

[Serializable]
class Trouble
{
   public Trouble t1;
   public Trouble t2;
   public Trouble t3;
}

不支持多态:待理解

 

如果我们要正确的序列化以上问题,就要用ISerializationCallbackReceiver接口:

    OnBeforeSerialize():

                                这个方法是运行在Unity序列化前, 用来通知你Unity将准备序列化

    OnAfterDeserialize():

                                 这个方法是运行在Unity序列化后,用来通知你Unity将已经序列化完

例如我想创建一个序列化树类型 类里面有为Null变量, 违反了第二条限制,直接让Unity运行序列化,将会导致树类型数据很大, 性能下降.

技术分享
using UnityEngine;
using System.Collections.Generic;
using System;

public class VerySlowBehaviourDoNotDoThis : MonoBehaviour
{
    [Serializable]
    public class Node
    {
        public string interestingValue = "value";

        //The field below is what makes the serialization data become huge because
        //it introduces a ‘class cycle‘.
        public List<Node> children = new List<Node>();
    }
    
    //this gets serialized  
    public Node root = new Node();  

    void OnGUI()
    {
        Display (root);
    }

    void Display(Node node)
    {
        GUILayout.Label ("Value: ");
        node.interestingValue = GUILayout.TextField(node.interestingValue, GUILayout.Width(200));

        GUILayout.BeginHorizontal ();
        GUILayout.Space (20);
        GUILayout.BeginVertical ();

        foreach (var child in node.children)
            Display (child);
        if (GUILayout.Button ("Add child"))
            node.children.Add (new Node ());

        GUILayout.EndVertical ();
        GUILayout.EndHorizontal ();
    }
}
View Code

解决的方法使用ISerializationCallbackReceiver接口: 让你生成一个缓存变量来序列化,而不是直接序列化一个树类型

技术分享
using UnityEngine;
using System.Collections.Generic;
using System;

public class BehaviourWithTree : MonoBehaviour, ISerializationCallbackReceiver
{
    //node class that is used at runtime
    public class Node
    {
        public string interestingValue = "value";
        public List<Node> children = new List<Node>();
    }

    //node class that we will use for serialization
    [Serializable]
    public struct SerializableNode
    {
        public string interestingValue;
        public int childCount;
        public int indexOfFirstChild;
    }

    //the root of what we use at runtime. not serialized.
    Node root = new Node(); 

    //the field we give unity to serialize.
    public List<SerializableNode> serializedNodes;

    public void OnBeforeSerialize()
    {
        //unity is about to read the serializedNodes field‘s contents. lets make sure
        //we write out the correct data into that field "just in time".
        serializedNodes.Clear();
        AddNodeToSerializedNodes(root);
    }

    void AddNodeToSerializedNodes(Node n)
    {
        var serializedNode = new SerializableNode () {
            interestingValue = n.interestingValue,
            childCount = n.children.Count,
            indexOfFirstChild = serializedNodes.Count+1
        };
        serializedNodes.Add (serializedNode);
        foreach (var child in n.children)
            AddNodeToSerializedNodes (child);
    }

    public void OnAfterDeserialize()
    {
        //Unity has just written new data into the serializedNodes field.
        //let‘s populate our actual runtime data with those new values.

        if (serializedNodes.Count > 0)
            root = ReadNodeFromSerializedNodes (0);
        else
            root = new Node ();
    }

    Node ReadNodeFromSerializedNodes(int index)
    {
        var serializedNode = serializedNodes [index];
        var children = new List<Node> ();
        for(int i=0; i!= serializedNode.childCount; i++)
            children.Add(ReadNodeFromSerializedNodes(serializedNode.indexOfFirstChild + i));
    
        return new Node() {
            interestingValue = serializedNode.interestingValue,
            children = children
        };
    }

    void OnGUI()
    {
        Display (root);
    }

    void Display(Node node)
    {
        GUILayout.Label ("Value: ");
        node.interestingValue = GUILayout.TextField(node.interestingValue, GUILayout.Width(200));

        GUILayout.BeginHorizontal ();
        GUILayout.Space (20);
        GUILayout.BeginVertical ();

        foreach (var child in node.children)
            Display (child);
        if (GUILayout.Button ("Add child"))
            node.children.Add (new Node ());

        GUILayout.EndVertical ();
        GUILayout.EndHorizontal ();
    }
}
View Code

要小心使用序列化,因为序列化并不是运行在主线程!

 

Unity 序列化 总结

标签:

原文地址:http://www.cnblogs.com/devhyj/p/4342592.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!