[cb]ScriptableObject 序列化

简介:



ScriptableObject

       ScriptableObject是一个类,它允许你存储大量用于共享的数据独立脚本实例,不要迷惑这个类同样可以叫做 SerializableObject,可以理解成是一个Unity串行化工具。这是一个编辑器类并且你可以在Inspector面板中编辑数据。例如:如果你有一个存储了一百万数据的 int[],这个数组占用4MB内存,放在Prefab上,那么当你每次实例化Prefab,你都会得到这个数组的一个副本。如果你实例化10个这个Prefab,那就会占用40MB内存。

可序列化的类型

Unity的serializes(序列化)支持所有原生的类型,也支持strings,arrays,lists还有Unity的Vector3等都支持,而且还支持自定义的类,但需要有一个串行的属性。

使用情景

预期使用情况,使用ScriptableObject是减少内存使用量,避免Values的副本。但是你也可以用它来定义可插拨的数据集。这方面的一个例子是:想像RPG游戏中的NPC商店,你可以创建自定义ShopContens ScriptableObject,每个资产定义了一组可用于购买物品。在这样一个场景,游戏中有三个区域,每个区域都可以提供不同层级的项目。你的店铺脚本将引用ShopContents对象,定义哪些项目可供选择。

 

Tips

当在检查ScriptableObject引用时,你可以在Inspector双击这个参考字段。

你可以创建一个自定义的Editor来查看不同的类似在Inspector,以帮助你管理它所表示的数据。

游戏关卡数据序列化

策划需求

一个游戏中的配置表数据,这些数据一般都是由策划在Excel等工具上配置,要运用到游戏中时,一般需要做一个转换,比如类似转换。这时可以使用ScriptableObject,将数据预先处理成程序需要访问的数据结构,存储在ScriptableObject中,然后打包成一个外部文件,这样在游戏运行的时候就不用做解析和组装了,这个功能对大批量的公用数据尤其有用!!

思路分析

策划在Art工程拼接好关卡信息之后,客户端根据关卡的中元素的位置,大小等信息生成出关卡,这中间有一个存储关卡信息的过程。我们的做法是把关卡的信息存储在ScriptableObject上,然后在Editor里,把当前关卡信息存储在Product目录下做为一个文件。Client直接读取这个MapObject文件

MapSetting.cs

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

//地图信息打包成外部文件,供Client读取
public class CMapSetting : ScriptableObject
{
    public List<string> TexturesDependencies;//依赖的贴图
    public string MapObjectPath;//MapRoot

    public List<CLevelBattleSetting> Battles;//战役信息
}

导出关卡数据代码

    public void ExportCurrentScene()
    {
        SceneName = EditorApplication.currentScene.Substring(EditorApplication.currentScene.LastIndexOf('/') + 1);
        SceneName = SceneName.Substring(0, SceneName.LastIndexOf('.'));
        string exportPath = string.Format("Scene/{0}{1}", SceneName, GameDef.ASSET_BUNDLE_FILE_EXT);

        string mapObjectPath = string.Format("Scene/{0}_MapObject{1}", SceneName, GameDef.ASSET_BUNDLE_FILE_EXT);

        CSimBattle[] battles = GameObject.FindObjectsOfType<CSimBattle>();//获取所有的Battle

        List<CSimBattle> battleList = new List<CSimBattle>(battles);
        battleList.Sort((CSimBattle x, CSimBattle y) =>
        {
            return x.transform.position.y.CompareTo(y.transform.position.y);
        });//根据Battle的Y进行排序

        CSimActor[] actors = GameObject.FindObjectsOfType<CSimActor>();//获取所有的Actor
        List<CSimActor> actorList = new List<CSimActor>(actors);
        int count = 0;//测试一个Battle中多少只怪
        List<CLevelBattleSetting> LevelBattleSettings = new List<CLevelBattleSetting>();//有多少关卡

        for (int b = 0; b < battleList.Count; b++)//遍历Battle
        {
            CSimBattle simBattle = battleList[b];
            CLevelBattleSetting levelBatSetting = new CLevelBattleSetting();//创建一个新的BattleSetting实例
            levelBatSetting.MapActorSettings = new List<CMapActorSetting>();//Battle中的Actor设置信息
            levelBatSetting.Num = simBattle.KillNum;
            levelBatSetting.Time = simBattle.BattleTime;
            levelBatSetting.StoryOnStart = simBattle.StoryOnStart;
            levelBatSetting.StoryOnEnd = simBattle.StoryOnEnd;
            levelBatSetting.CurPosition = simBattle.transform.position;
            //CBase.Log("CSimBattle.CurPosition:{0}", levelBatSetting.CurPosition);

            float battlePosY = simBattle.transform.position.y;//Battle的Y值
            for (int a = (actorList.Count - 1); a >= 0; a--)//遍历怪
            {
                float actorPosY = actorList[a].transform.position.y;//Actor的Y值
                if (actorPosY <= battlePosY)//判断这个Actor是否在这个Battle内
                {
                    CMapActorSetting actorSetting = new CMapActorSetting();
                    CSimActor simActor = actorList[a];
                    actorSetting.NpcId = simActor.NPC编号;
                    actorSetting.NpcLevel = simActor.NPC等级;
                    actorSetting.NpcPosition = simActor.transform.position;
                    actorSetting.IsEnemy = simActor.是否敌人;

                    levelBatSetting.MapActorSettings.Add(actorSetting);//把怪添加到关卡中
                    actorList.Remove(simActor);//移除已经添加的Actor
                    count += 1;
                }
            }

            LevelBattleSettings.Add(levelBatSetting);//把battle添加进关卡地图中
            CBase.Log("Battle :{0}  有怪物 {1} 只" ,b, count);//打印一个Battle中有多少怪
            count = 0;
        }
        //CBase.Log("当前关卡共有 {1} 个Battle", LevelBattleSettings.Count);

        GameObject mapRoot = GameObject.Find("MapRoot");
        if (mapRoot != null)
        {
            List<string> textureList = new List<string>();//存放打包好图片的路径
            Renderer[] renderers = mapRoot.GetComponentsInChildren<Renderer>();
            foreach (Renderer child in renderers)
            {
                Texture _texture = child.sharedMaterial.mainTexture;
                string _path = AssetDatabase.GetAssetPath(_texture);
                _path = XBuildTools.GetUniquepath(_path);
                if (!textureList.Contains(_path))
                {
                    textureList.Add(_path);
                    XBuildTools.PushAssetBundle(_texture, string.Format("Textures/{0}{1}", _path, GameDef.ASSET_BUNDLE_FILE_EXT));
                    CBase.Log("Texture导出成功! =>{0}", _path);
                }
            }

            XBuildTools.PushAssetBundle(mapRoot, mapObjectPath);//打包 mapRoot
            Debug.Log("地图导出成功!" + SceneName);
            XBuildTools.PopAssetBundle();
            //XBuildTools.PopAllAssetBundle();

            CMapSetting mapSetting = ScriptableObject.CreateInstance<CMapSetting>();
            mapSetting.TexturesDependencies = textureList;
            mapSetting.MapObjectPath = mapObjectPath;
            mapSetting.Battles = LevelBattleSettings;
            XBuildTools.BuildScriptableObject(mapSetting, exportPath);//序列化 MapSetting的位置啊,路径信息。
        }
    }

打包出的关卡文件

image

文档资料

Unity Manual:http://docs.unity3d.com/Manual/class-ScriptableObject.html

Scripting API:http://docs.unity3d.com/ScriptReference/ScriptableObject.html


本文转自赵青青博客园博客,原文链接:http://www.cnblogs.com/zhaoqingqing/p/3775069.html,如需转载请自行联系原作者

相关文章
|
2月前
|
JSON 数据格式 C++
[序列化协议] --- JSON
[序列化协议] --- JSON
30 0
|
11月前
|
Dubbo Java 应用服务中间件
再谈序列化之rpc调用失败和jackson序列化时不允许Map中的key为null
再谈序列化之rpc调用失败和jackson序列化时不允许Map中的key为null
181 0
|
XML Java 数据格式
返回对象的序列化实现
返回对象的序列化实现
108 0
json.Unmarshal() 反序列化字节流到 interface{} 对象,字段 int/int64 类型出现精度丢失
json.Unmarshal() 反序列化字节流到 interface{} 对象,字段 int/int64 类型出现精度丢失
Lexicography——CF1267L构造题
Lucy likes letters. She studied the definition of the lexicographical order at school and plays with it. At first, she tried to construct the lexicographically smallest word out of given letters. It was so easy! Then she tried to build multiple words and minimize one of them. This was much harder!
216 0
组装数据- 对象里面是key:value, value里面是数组的形式,如 {key:[aa,bb], key:[cc,dd]}
组装数据- 对象里面是key:value, value里面是数组的形式,如 {key:[aa,bb], key:[cc,dd]}
组装数据- 对象里面是key:value, value里面是数组的形式,如 {key:[aa,bb], key:[cc,dd]}
|
存储 Java 编译器
关于序列化的 10 几个问题,你顶得住不?.md
任何序列化该类的尝试都会因NotSerializableException而失败,但这可以通过在 Java中 为 static 设置瞬态(transient)变量来轻松解决。
关于序列化的 10 几个问题,你顶得住不?.md
|
JSON Java 数据格式
总共4行代码使用fastxml.json实现Java对象的序列化和反序列化
总共4行代码使用fastxml.json实现Java对象的序列化和反序列化
293 0
总共4行代码使用fastxml.json实现Java对象的序列化和反序列化
|
XML 测试技术 数据格式
|
JSON JavaScript Android开发