Unity进阶之ScriptableObject

目录

  • ScriptableObject 概述
  • ScriptableObject数据文件的创建
  • 数据文件的使用
  • 非持久数据
  • 让其真正意义上的持久
  • ScriptableObject的应用
    • 配置数据
    • 复用数据
    • 数据带来的多态行为
    • 单例模式化的获取数据

ScriptableObject 概述

ScriptableObject是什么
ScriptableObject是Unity提供的一个数据配置存储基类
它是一个可以用来保存大量数据的数据容器
就像是可以自定义的数据资源文件
它是一个类似MonoBehavior的基类
需要我们继承它来进行使用
它的主要作用是
1.数据复用(多个对象用同一个数据)
2.配置文件(配置游戏中的数据)
3.编辑模式下的数据持久化
数据复用
比如一个子弹对象
以前我们通过面向对象的思想去做的话
会写一个继承MonoBehaviour的脚本
相关的属性都会在这里声明
然后挂载到子弹模型预设体上
这样每次实例化一个子弹,如果数据不变
那么对内存来说,是有一定浪费的
因为每一个子弹预设体上都有该脚本
那么所有的属性都会分配一次内存
通过使用ScriptableObject可以有效避免内存的浪费
配置文件
以前我们要通过配置文件配置游戏相关的数据,比如玩家数据、怪物数据等等
是通过数据持久化相关知识来完成的,我们一般会通过xml、json、excel等方式来配置游戏数据
相对来说都是在Unity外部通过其它格式的文件对数据进行配置
而通过ScriptableObject我们可以直接在Unity内部
在Inspector窗口中就可以进行数据的配置
编辑模式下的数据持久化
当我们在编辑模式下修改了继承ScriptableObject对象的数据文件内容时
这些修改将被记录下来
因此在编辑模式下ScriptableObject是具有数据持久化特性的

但是需要注意的是,在发布运行时
ScriptableObject并不具备持久化特性(修改数据对象,并不会保存在本地)
ScriptableObject的好处
1.我们可以直接在Inspector窗口编辑配置数据,可以利用它来做配置文件
2.处理重复数据,减少数据拷贝时造成的内存占用,可以利用它来做公共数据
3.可以更方便的处理数据带来的多态行为

ScriptableObject数据文件的创建

自定义ScriptableObject数据容器
1.继承ScriptableObject类
2.在该类中声明成员(变量、方法等)

注意:声明后,我们边可以在Inspector窗口中看到变化
我们可以在其中进行设置,但是这些设置都是默认数据,并没有真正使用他们
这些关联信息都是通过脚本文件对应的Unity配置文件meta进行记录的
目前该数据只是一个数据容器模板
有了它我们之后才能根据它的信息创建对应的数据资源文件

根据自定义的ScriptableObject数据容器创建数据文件
注意:
该创建功能,其实就是根据自定义数据容器类创建了一个配置文件
该文件中记录了对应的数据容器类信息,以及其中变量关联的信息
之后我们在使用它时,本质上也是通过反射创建对象进行使用

具体的方法有两种:
//1.为类添加CreateAssetMenu通过菜单创建资源特性
[CreateAssetMenu(fileName = “默认文件名”, menuName = “在Asset/Create菜单中显示的名字”, order = 再Asset/Create菜单中的位置(多个时可以通过它来调整顺序))]

2.利用ScriptableObject的静态方法创建数据对象
然后将数据对象保存在工程目录下

public class ScriptableObjectTool
{[MenuItem("ScriptableObject/CreateMyData")]public static void CreateMyData(){//书写创建数据资源文件的代码MyData asset = ScriptableObject.CreateInstance<MyData>();//通过编辑器API 根据数据创建一个数据资源文件AssetDatabase.CreateAsset(asset, "Assets/Resources/MyDataTest.asset");//保存创建的资源AssetDatabase.SaveAssets();//刷新界面AssetDatabase.Refresh();}
}

ScriptableObject好处的体现
1.更方便的配置数据,我们可以直接在Inspector当中配置数据
2.项目之间的复用,我们可以拷贝继承ScriptableObject的脚本到任何工程中

数据文件的使用

ScriptableObject数据文件的使用
1.通过Inspector中的public变量进行关联
1-1.创建一个数据文件
1-2.在继承MonoBehaviour类中申明数据容器类型的成员
在Inspector窗口进行关联

2.通过资源加载的信息关联
加载数据文件资源
注意:Resources、AB包、Addressables都支持加载继承ScriptableObject的数据文件

data = Resources.Load<MyData>("MyDataTest");
data.PrintInfo();

注意:如果多个对象关联同一个数据容器文件,他们共享的是一个对象
因为是引用对象,所以在其中任何地方修改后,其它地方也会发生改变

ScriptableObject的生命周期函数
ScriptableObject和MonoBehavior很类似
它也存在生命周期函数
但是生命周期函数的数量更少
主要做了解,一般我们使用较少

Awake 数据文件创建时调用

OnDestroy ScriptableObject 对象将被销毁时调用
OnDisable ScriptableObject 对象销毁时、即将重新加载脚本程序集时 调用
OnEnable ScriptableObject 创建或者加载对象时调用

OnValidate 编辑器才会调用的函数,Unity在加载脚本或者Inspector窗口中更改值时调用
ScriptableObject好处的体现
1.编辑器中的数据持久化
通过代码修改数据对象中内容,会影响数据文件
相当于达到了编辑器中数据持久化的目的
(该数据持久化 只是在编辑模式下的持久,发布运行时并不会保存数据)
2.复用数据
如果多个对象关联同一个数据文件
相当于他们复用了一组数据,内存上更加节约空间

非持久数据

ScriptableObject的非持久化数据指的是什么
指的是不管在编辑器模式还是在发布后都 不会持久化的数据
我们可以根据自己的需求随时创建对应数据对象进行使用
就好像直接new一个数据结构类对象
如何利用ScriptableObject生成非持久化的数据
利用ScriptableObject中的静态方法 CreateInstance<>()
该方法可以在运行时创建出指定继承ScriptableObject的对象
该对象只存在于内存当中,可以被GC
调用一次就创建一次

通过这种方式创建出来的数据对象 它里面的默认值 不会受到脚本中设置的影响
ScriptableObject的非持久化数据存在的意义
只是希望在运行时能有一组唯一的数据可以使用
但是这个数据又不太希望保存为数据资源文件浪费硬盘空间
那么ScriptableObject的非持久化数据就有了存在的意义
它的特点是
只在运行时使用,在编辑器模式下也不会保存在本地

让其真正意义上的持久

利用Json结合ScriptableObject存储数据

data.PrintInfo();data.i = 9999;
data.f = 6.6f;
data.b = true;
//将数据对象 序列化为 json字符串
string str = JsonUtility.ToJson(data);
print(str);
//把数据序列化后的结果 存入指定路径当中
File.WriteAllText(Application.persistentDataPath + "/testJson.json", str);
print(Application.persistentDataPath);

利用Json结合ScriptableObject读取数据

//从本地读取 Json字符串
string str = File.ReadAllText(Application.persistentDataPath + "/testJson.json");
//根据json字符串反序列化出数据 将内容覆盖到数据对象中
JsonUtility.FromJsonOverwrite(str, data);
data.PrintInfo();

ScriptableObject的应用

配置数据

ScriptableObject数据文件为什么非常适合用来做配置文件?
1.配置文件的数据在游戏发布之前定规则
2.配置文件的数据在游戏运行时只会读出来使用,不会改变内容
3.在Unity的Inspector窗口进行配置更加的方便
举例制作
以前我们的常规配置方式
都是利用之前学习过的 数据持久化四部曲当中的内容进行配置的
比如 xml配置 json配 置 excel配置
1、创建RoleInfo.cs脚本

[CreateAssetMenu(fileName ="RoleInfo", menuName = "ScriptableObject/角色信息")]
public class RoleInfo : ScriptableObject
{[System.Serializable]public class RoleData{public int id;public string res;public int atk;public string tips;public int lockMoney;public int type;public string hitEff;public void Print(){Debug.Log(id);Debug.Log(res);Debug.Log(atk);Debug.Log(tips);Debug.Log(lockMoney);Debug.Log(type);Debug.Log(hitEff);}}public List<RoleData> roleList;
}

2、使用数据

public RoleInfo info;
for (int i = 0; i < info.roleList.Count; i++)
{info.roleList[i].Print();
}

我们可以利用ScriptableObject数据文件 来制作编辑器相关功能
比如:Unity内置的技能编辑器、关卡编辑器等等
我们不需要把编辑器生成的数据生成别的数据文件,而是直接通过ScriptableObject进行存储
因为内置编辑器只会在编辑模式下运行,编辑模式下ScriptableObject具备数据持久化的特性

复用数据

使用预设体对象可能存在的内存浪费问题
对于只用不变的数据
以面向对象的思想去声明对象类是可能存在内存浪费的问题的
举例说明 利用ScriptableObject数据对象 更加节约内存
1、创建BulletInfo.cs脚本

[CreateAssetMenu()]
public class BulletInfo : ScriptableObject
{public float speed;public int atk;
}

2、创建Bullet脚本

public class Bullet : MonoBehaviour
{public BulletInfo info;// Start is called before the first frame updatevoid Start(){}// Update is called once per framevoid Update(){this.transform.Translate(Vector3.forward * info.speed * Time.deltaTime);}
}

数据带来的多态行为

某些行为的变化是因为数据的不同带来的
我们可以利用面向对象的特性和原则,以及设计模式相关知识点
结合ScriptableObject做出更加方便的功能

比如随机音效,物品拾取,AI等等等
随机音效(里氏替换原则和依赖倒转原则)
播放音乐时,可能会随机播放多个音效当中的一种

物品拾取(里氏替换原则和依赖倒转原则)
比如拾取一个物品,物品给玩家带来不同的效果

AI
不同数据带来的不同行为模式

为了方便我们使用,我们可以利用ScriptableObject的可配置性来制作这些功能
举例讲解

单例模式化的获取数据

为什么要单例模式化的获取数据
对于只用不变并且要复用的数据
比如配置文件中的数据
我们往往需要在很多地方获取他们
如果我们直接通过在脚本中 public关联 或者 动态加载
如果在多处使用,会存在很多重复代码,效率较低
如果我们将此类数据通过单例模式化的去获取
可以提升效率,减少代码量
实现单例模式化获取数据
知识点
面向对象、单例模式、泛型等等

我们可以实现一个ScriptableObject数据单例模式基类
让我们只需要让子类继承该基类
就可以直接获取到数据
而不再需要去通过 public关联 和 资源动态加载
1、创建SingleScriptableObject.cs脚本

public class SingleScriptableObject<T> :ScriptableObject where T:ScriptableObject
{private static T instance;public static T Instance{get{//如果为空 首先应该去资源路劲下加载 对应的 数据资源文件if (instance == null){//我们定两个规则//1.所有的 数据资源文件都放在 Resources文件夹下的ScriptableObject中//2.需要复用的 唯一的数据资源文件名 我们定一个规则:和类名是一样的instance = Resources.Load<T>("ScriptableObject/" + typeof(T).Name);}//如果没有这个文件 为了安全起见 我们可以在这直接创建一个数据if(instance==null){instance = CreateInstance<T>();}//甚至可以在这里 从json当中读取数据,但是我不建议用ScriptableObject来做数据持久化return instance;}}
}

2、使用:将RoleInfo继承该类
在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/4101.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

有没有电脑桌面监控软件|十大电脑屏幕监控软件超全盘点!

电脑桌面监控软件已经成为许多领域不可或缺的工具。 无论是企业为了保障数据安全和提高工作效率&#xff0c;还是家长为了监督孩子的学习&#xff0c;甚至是个人为了记录电脑使用行为&#xff0c;都需要这类软件的支持。 本文将对市面上十大电脑屏幕监控软件进行超全盘点&…

智能文案生成器,文案生成改写很强大

在当今数字化时代&#xff0c;随着人工智能的迅猛发展&#xff0c;智能文案生成器正逐渐成为营销和创作领域的一大利器。这些智能工具不仅能够快速生成文案&#xff0c;还能够进行文案改写&#xff0c;使得文案生成的过程更加高效、便捷。正是在这样的背景下&#xff0c;智能文…

CAT:contig稳健物种分类

安装 mamba create -n CAT python3.10 diamond prodigal cd SoftWare git clone https://github.com/MGXlab/CAT_pack chmod 755 给权限 自己构建数据库 names.dmp nodes.dmp文件可以在Kraken2的文件里面找到 Kraken2Bracken&#xff1a;宏基因组物种注释_kracken2配合bracke…

MySQL之binlog归档日志

binlog&#xff08;二进制归档日志&#xff09; binlog 二进制日志记录保存所有执行过的修改操作语句&#xff0c;不保存查询操作。如果 MySQL 服务意外停止&#xff0c;可通过二进制日志文件排查&#xff0c;用户操作或表结构操作&#xff0c;从而来恢复数据库数据。启动 bin…

Java 线程的几种状态

一、 线程的状态 状态是针对当前的线程调度的情况来描述的。因为线程是调度的基本单位&#xff0c;所以状态更应该是线程的属性。在Java中线程的状态一共有六种&#xff1a; 1. 初始(NEW)&#xff1a;新创建了一个线程对象&#xff0c;但还没有调用start()方法。 2. 运行(RUNN…

动静态库以及动态链接

文章目录 静态库制作静态库如何使用静态库 动态库动态库的制作动态库的使用动态链接 库是给别人用的&#xff0c;所以库中一定不存在main函数。库一般会有lib前缀和后缀&#xff0c;去掉前缀和后缀才是库名。 静态库 静态库&#xff08;.a&#xff09;&#xff1a;程序在编译…

C++|对象与const

目录 常对象 常对象的声明 性质 数据成员不能被修改 常对象不能调用非const成员函数 const型成员函数 常对象成员 常数据成员 常成员函数 注意 总结 const型数据成员 const型成员函数 常对象 指针与const 指向对象的常指针 应用场景 指向常对象的指针 指向常…

Swagger3.0(Springdoc)日常使用记录

文章目录 前言一、默认地址二、注解OperationTag 三、SpringBoot基础配置四、Swagger导入apifox五、Swagger其他配置六 knife4j 参考文章 前言 本文并不是Swagger的使用教程&#xff0c;只是记录一下本人的操作&#xff0c;感兴趣的可以看下 一、默认地址 http://localhost:…

【1731】jsp 房租跟踪监控管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 JSP 房租跟踪监控管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysq…

Java 基础常见面试题整理

目录 1、java的基本数据类型有哪些&#xff1f;2、java为什么要有包装类型&#xff1f;3、String a "123" 和 String a new String("123") 区别&#xff1f;4、String、StringBuilder和StringBuffer的区别&#xff1f;5、如何理解面向对象和面向过程&…

浅谈叉车车载电脑的市场现状

叉车的起源 叉车源于美国&#xff0c;兴于日本&#xff0c;虽然中国起步较晚&#xff0c;但是近些年来发展迅速。叉车又称叉式装载车&#xff0c;是对于成件托盘类货物进行装卸、堆垛和短距离运输&#xff0c;实现重物搬运作业的轮式工业车辆。 叉车的分类 叉车分为以上六大类…

CSS学习(选择器、盒子模型)

1、CSS了解 CSS&#xff1a;层叠样式表&#xff0c;一种标记语言&#xff0c;用于给HTML结构设置样式。 样式&#xff1a;文字大小、背景颜色等 p标签内不能嵌套标题标签。 px是相对于分辨率而言的&#xff0c; em是相对于浏览器的默认字体&#xff0c; rem是相对于HTML根元…

刷题日记 ---- 顺序表与链表相关经典算法题(C语言版)

目录 1. 移除元素2. 合并两个有序数组3. 移除链表元素4. 反转链表5. 合并两个有序链表6. 链表的中间结点7. 环形链表的约瑟夫问题8. 分割链表总结 正文开始 1. 移除元素 题目链接: 移除元素 题目描述: 思路历程: 题目明确要求, 不能使用额外的数组空间, 也就是说不可以创建…

【优质书籍推荐】AIGC时代的PyTorch 深度学习与企业级项目实战

大家好&#xff0c;我是herosunly。985院校硕士毕业&#xff0c;现担任算法研究员一职&#xff0c;热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名&#xff0c;CCF比赛第二名&#xff0c;科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的…

springcloud按版本发布微服务达到不停机更新的效果

本文基于以下环境完成 spring-boot 2.3.2.RELEASEspring-cloud Hoxton.SR9spring-cloud-alibaba 2.2.6.RELEASEspring-cloud-starter-gateway 2.2.6.RELEASEspring-cloud-starter-loadbalancer 2.2.6.RELEASEnacos 2.0.3 一、思路 实现思路&#xff1a; 前端项目在请求后端接…

C++ 哈希

&#x1f493;博主CSDN主页:麻辣韭菜&#x1f493;   ⏩专栏分类&#xff1a;C知识分享⏪   &#x1f69a;代码仓库:C高阶&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习更多C知识   &#x1f51d;&#x1f51d; ​ 前言 1. unordered系列关联式容器 1.1 unor…

必应bing国内广告开户注册教程!

今天搜索引擎广告成为企业推广产品与服务、提升品牌知名度的重要渠道之一。作为全球第二大搜索引擎&#xff0c;必应Bing凭借其高质量的用户群体和广泛的国际覆盖&#xff0c;为广告主提供了独特的市场机遇。在中国&#xff0c;虽然必应的市场份额相对较小&#xff0c;但对于寻…

磁密固定下的三次谐波与电压谐波的关系

同相位或者相位差为180的情况下&#xff0c;磁通密度三次谐波含量占比 α \alpha α&#xff0c;则电压三次谐波含量占比为 3 α 3\alpha 3α 同相位&#xff0c;磁通密度三次谐波含量占比 α \alpha α情况下&#xff0c; B B 0 sin ⁡ ( ω t ) α B 0 sin ⁡ ( 3 ω t )…

航空企业数字化解决方案(207页PPT)

一、资料描述 航空企业数字化解决方案是一项针对航空公司在数字化转型过程中所面临挑战的全面应对策略&#xff0c;旨在通过先进的信息技术提升航空企业的运营效率、客户服务水平以及市场竞争力。这份207页的PPT详细介绍了航空企业数字化的各个方面&#xff0c;包括关键技术的…

Web3技术解析:区块链在去中心化应用中的角色

引言 在过去几年中&#xff0c;Web3技术已经成为了互联网领域的一个热门话题。作为区块链技术的延伸&#xff0c;Web3不仅仅是数字货币的代名词&#xff0c;更是一个能够为各种应用提供去中心化解决方案的强大工具。本文将深入探讨区块链在Web3去中心化应用中的关键角色&#…