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;//MapRootpublic 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>();//获取所有的BattleList<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>();//获取所有的ActorList<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);//移除已经添加的Actorcount += 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);//打包 mapRootDebug.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的位置啊,路径信息。}}

打包出的关卡文件

文档资料

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

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

[cb]ScriptableObject 序列化相关推荐

  1. Unity中的序列化和反序列化

    一:前言 序列化是指把对象转换为字节序列的过程,而反序列化是指把字节序列恢复为对象的过程.序列化最主要的用途就是传递对象和保存对象 在Unity中保存和加载.prefab.scene.Inspecto ...

  2. Unity加载配置文件的几种方式

    版权声明:本文为CSDN博主「萌新求带」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明. 原文链接:https://blog.csdn.net/qq_17758883 ...

  3. Unity工程文件夹里的目录结构

    M 1.特殊文件夹 Assets Library ProjectSettings Editor Editor Default Resources Gizmos Plugins Resources St ...

  4. Unity 中配置文件Excel 转xml ;josn;序列化ScriptableObject及加载(最详细)。

    游戏中对策划的配置数据导入处理常用分为1.转xml或josn.2.序列化为ScriptableObject类.第一种方法游戏加载耗时一些,第二种避免了第一种方法加载缺点但内存要占用大一些.不过推荐第二 ...

  5. Java序列化的机制和原理

    有关Java对象的序列化和反序列化也算是Java基础的一部分,下面对Java序列化的机制和原理进行一些介绍. Java序列化算法透析 Serialization(序列化)是一种将对象以一连串的字节描述 ...

  6. java序列化算法透析_Java序列化机制与原理的深入分析

    Java序列化算法透析 Serialization(序列化)是一种将对象以一连串的字节描述的过程:反序列化deserialization是一种将这些字节重建成一个对象的过程.Java序列化API提供一 ...

  7. [Unity] ACT 战斗系统学习 7:使用 ScriptableObject 制作角色属性 2

    本来我是以为泛型 ScriptableObject 是不可能的 但是我之前在制作技能条件时的尝试让我感觉到一个可能性 当时我是做成这样子的 其实这已经很好看了 当时我是实现了获取一个已知物体的所有字段 ...

  8. [Unity] ACT 战斗系统学习 5:使用 ScriptableObject 制作角色属性 1

    首先最重要的是属性 // ---------------------------------------------- // 作者: 廉价喵 // 创建于: 29/03/2022 1:19 // 最后 ...

  9. 非常好用的游戏数据保存类:ScriptableObject

    基础知识: 1.将数据储存资源文件中,像普通资源一样管理,退出也会保存修改 2.继承自UnityEngine.Object,不必附着在对象上也无需/不能赋给Gameobject或Prefab 3.可以 ...

最新文章

  1. MySQL查看表结构的实际操作命令简介
  2. Oren NayarModel
  3. 【多态】多态的向下转型
  4. css3 的 calc()函数在布局中的使用----头部高度固定,页面正好占满一屏
  5. LeetCode 452. 用最少数量的箭打破气球(贪心)
  6. 推荐系统--矩阵分解(1)
  7. 计算机专业本科毕业答辩问题及回答
  8. 2017行进中的杂想,做一个极少数的历史
  9. 安装Python解释器【图文集合 - 详细流程】
  10. 博客搬家日记--搭建基于Docker的LNMP环境
  11. 我的世界观【文津图书奖获奖作品】
  12. 自制STM32F205最小系统板
  13. r语言 断轴 画图_R语言之画图(一)
  14. 【Matlab图像加密】Logistic+Tent+Kent+Henon图像加密与解密【含GUI源码 1745期】
  15. 微信小程序-文字跑马灯
  16. “80后”!顶尖985,迎新副校长!
  17. Android malware样本SLocker Mobile Ransomware
  18. unity 导入gltf_GLTF相关资料
  19. 计算机体系结构——1.1 计算机体系结构的概念与发展
  20. KiTTY及cnKiTTY配置文件kitty.ini的简单中文注释

热门文章

  1. java-将xlsx(excel)文件转换成json
  2. 宝塔Linux 8888 进不去
  3. 大数据怎样帮助运维工程师实现无死角监控?
  4. webstrom命名改名 命令
  5. Android自定义View之paint(一)
  6. 修改UCenter用户名长度限制的方法php程序和数据库修改
  7. shell编程中if []的用法注意
  8. WinAPI: waveInGetPosition - 获取当前输入设备的输入位置
  9. Bugzilla简明使用手则
  10. 共享内存+互斥量实现 Linux 进程间通信