Unity序列化

本文详细介绍了Unity中ScriptableObject的使用方法,包括如何创建、序列化及加载ScriptableObject实例,展示了如何利用它来存储和管理游戏数据,提高数据加载速度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ScriptableObject

参考网址

ScriptableObject类型经常用于存储一些unity3d本身不可以打包的一些object,比如字符串,一些类对象等。

[System.Serializable]
public class SkillItem
{
    public int skillid;
    public string skillname;
}

[System.Serializable]
public class GameDataScriptable :ScriptableObject
{
    public List<SkillItem> skillItemList = new List<SkillItem>();
}

打包ScriptObject,ScriptObject 可以存储任何数据类型

//通过ScriptableObject创建一个对象的实例  
GameDataScriptable gs = ScriptableObject.CreateInstance<GameDataScriptable>();  
//对对象的属性进行赋值  
for(int i=1;i<3;i++){  
    SkillItem item = new SkillItem();  
    item.SkillId = i;                 
    item.SkillName = "技能" + i;    
    gs.SkillDictionary.Add(item);  
}
 //创建资源文件(可以在编辑器下直接编辑数据)  
AssetDatabase.CreateAsset(gs, "Assets/GameDataConfig.asset");  
//将资源反序列化为一个对象  
Object o = AssetDatabase.LoadAssetAtPath("Assets/GameDataConfig.asset", typeof(GameDataScriptable));  
//assetbundle文件只能在运行时加载,并且只能通过WWW加载  
BuildPipeline.BuildAssetBundle(o, null, "Assets/GameData.assetbundle");  
//删除临时的资源文件  
AssetDatabase.DeleteAsset("Assets/GameDataConfig.asset");  

运行时加载这个数据资源

public class LoadFile:MonoBehaviour  
{  
    IEnumerator Start ()  
    {  
      WWW www = new WWW("file://" + Application.dataPath + "/../GameDataConfig.assetbundle");  
      yield return www;  
      //转换资源为Test,这个test对象将拥有原来在编辑器中设置的数据。  
      GameDataScriptable test = www.assetBundle.mainAsset as GameDataScriptable;  
    }  
}  

提示:这其实就是把对象的实例打包,如果ScriptObject 属性中包括其他类的实例,则这些类需要加上[Serializable]序列化。通过这种方法,可以将系统需要的数据打包,
加载后直接转换为预定义的类型,可大大加快数据加载读取的速度,具有更高的效率。

SerializeField

强制Unity序列化私有变量
当Unity序列化脚本时,只会序列化公有成员,如果你也想序列化私有成员,可以添加上[SerializeField]属性

以下可被序列化:

  • 不是静态的公有成员
  • 不是静态,不是公有,被标记为[SerializeField]属性
  • 不能序列化 static 成员
  • 不能序列化 属性(properties)

Serializable

序列化类型:

  • 所有继承自UnityEngine.Object 的类,例如:GamObject,Component,MonoBehaviour,Texture2D,AnimationClip
  • 所有基础类型,例如 int,string,float,bool
  • 一些内置的类型,例如 Vactor2,Vector3,Vector4,Quaternion,Matrix4x4,Color,Rect,LayerMask
  • 可序列化类型的数组
  • 可序列化类型的List
  • Enums
  • Structs

注意:
1、不要将一个成员添加到数组或者list两次,当数组或者list被序列化的时候,你将得到这个成员两次,而在新的list或者数组再拷贝一份
2、Unity不会序列化字典,但是你可以将key,和value分别存储在list中

[System.Serializable]  
public class SerializableDictionary<TKey, TValue> : Dictionary<TKey, TValue>, ISerializationCallbackReceiver  
{  
    [SerializeField]  
    private List<TKey> _keys = new List<TKey>();  
    [SerializeField]  
    private List<TValue> _values = new List<TValue>();  

    public void OnBeforeSerialize()  
    {  
        _keys.Clear();  
        _values.Clear();  
        _keys.Capacity = this.Count;  
        _values.Capacity = this.Count;  
        foreach (var kvp in this)  
        {  
            _keys.Add(kvp.Key);  
            _values.Add(kvp.Value);  
        }  
    }  

    public void OnAfterDeserialize()  
    {  
        this.Clear();  
        int count = Mathf.Min(_keys.Count, _values.Count);  
        for (int i = 0; i < count; ++i)  
        {  
            this.Add(_keys[i], _values[i]);  
        }  
    }  
}  

//usage:
//[System.Serializable]  
//public class MyDictionary:SerializableDictionary<int,GameObject>{};
//public MyDictionary dic;

ISerializationCallbackReceiver是Unity提供的,可以在序列化/反序列化过程中监听回调的一个接口,需要实现OnBeforeSerializeOnAfterDeserialize两个方法

今天看到UWA更加详细的一篇,可作参考
Unity插件开发基础—浅谈序列化系统

Unity序列化机制是引擎内部的核心功能之一,广泛应用于编辑器和运行时环境中的数据保存与加载、资源管理以及 Inspector 面板的数据展示。理解其使用方法和原理对于开发者来说至关重要,能够帮助避免数据丢失、优化资源管理,并实现灵活的数据持久化方案。 ### 使用方法 Unity 提供了多种方式来控制序列化行为,开发者可以通过特性(Attribute)来标记需要序列化的字段或类。以下是一些常见的用法: - **`[SerializeField]`**:用于将私有字段暴露给 Unity 序列化系统并显示在 Inspector 中。 ```csharp [SerializeField] private int health; ``` - **`[System.Serializable]`**:用于标记一个类为可序列化,以便该类的实例可以被 Unity 正确地保存和加载。 ```csharp [System.Serializable] public class PlayerData { public string name; public int score; } ``` - **`[NonSerialized]`**:用于阻止某个字段被序列化,适用于不需要持久化的临时数据。 ```csharp [NonSerialized] private float tempValue; ``` - **`[HideInInspector]`**:结合 `[SerializeField]` 使用,隐藏字段在 Inspector 中的显示。 ```csharp [SerializeField, HideInInspector] private Vector3 position; ``` - **`[Range(min, max)]` 和 `[TextArea]`**:这些属性可以帮助限制用户输入范围或提供多行文本输入框,同时不影响序列化本身。 ```csharp [Range(0, 100)] [SerializeField] private int level; [TextArea] [SerializeField] private string description; ``` 此外,Unity 还支持复杂类型的序列化,例如 `List<T>` 和自定义结构体。为了确保类型安全和兼容性,建议对非基础类型使用 `[System.Serializable]` 标记[^4]。 ### 原理概述 Unity序列化机制基于反射和元信息(TypeTree)构建。每个可序列化类型都会生成一个描述其字段结构、类型、偏移量及大小等信息的 TypeTree。这个 TypeTree 被存储在资源文件(如 `.asset`, `.prefab`, `.unity`, `.bundle`)中,并在加载时指导反序列化过程。这种设计允许 Unity 在不同平台和版本之间保持良好的兼容性和灵活性[^3]。 当 Unity 对对象进行序列化时,它会遍历对象的所有字段,并根据它们是否带有 `[SerializeField]` 或者是公共字段决定是否将其包含进去。对于嵌套的对象或集合类型,Unity 会递归地处理每一个元素。如果遇到未标记为可序列化的类型,则抛出错误。因此,在定义需要被序列化的类时,必须加上 `[System.Serializable]` 特性[^4]。 在性能方面,Unity 提倡最小化序列化数据量以提高效率。例如,避免大型数组/列表,合理利用 ScriptableObject 存储静态数据,减少场景文件体积;对非必要数据使用 `[NonSerialized]` 属性,延迟加载动态数据等策略都是有效的优化手段[^2]。 通过上述方法和技术细节的应用,开发者可以在 Unity 中高效地管理和操作游戏或应用的数据状态,从而提升开发效率和产品质量。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值