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://xiahunao.cn/news/2980489.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

ElasticSearch笔记一

随着这个业务的发展&#xff0c;我们的数据量越来越庞大。那么传统的这种mysql的数据库就渐渐的难以满足我们复杂的业务需求了。 所以在微服务架构下一般都会用到一种分布式搜索的技术。那么今天呢我们就会带着大家去学习分布搜索当中最流行的一种ElasticSearch&#xff0c;Ela…

锂电池3.7V-4.2V降3.3V2.8V同步降压WT6015

锂电池3.7V-4.2V降3.3V2.8V同步降压WT6015 WT6015 是一款高效单片同步步降稳压器&#xff0c;采用恒定频率和电流模式架构。该设备提供可调节版本&#xff0c;适应不同的应用需求。在无负载条件下&#xff0c;其电源电流仅为40微安&#xff0c;而在关断状态下&#xff0c;电流…

HTB Runner

Runner User Nmap ──(root㉿kali)-[/home/…/machine/SeasonV/linux/Runner] └─# nmap -A runner.htb -T 4 Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-04-22 23:07 EDT Stats: 0:00:01 elapsed; 0 hosts completed (1 up), 1 undergoing SYN Stealth Sca…

【ks爬虫软件】把快手评论API接口封装成GUI采集工具

用Python开发爬虫采集软件&#xff0c;可自动抓取快手评论数据&#xff0c;且包含二级评论。 快手的评论接口URL&#xff1a; # 请求地址 url https://www.kuaishou.com/graphql开发者模式分析过程&#xff1a; 进而封装成GUI界面软件&#xff0c;如下&#xff1a; 软件效…

BI系统在银行有哪些应用场景?为什么说银行BI国产化是必然趋势?

银行业作为我国信息化程度最高的行业之一&#xff0c;最早开始迈出 IT国产化的步伐。然而&#xff0c;由于银行业数据的高度保密性、密集性、敏感性&#xff0c;以及业务的多元且复杂、对国家运行影响程度大&#xff0c;银行 IT国产化道阻且长。银行 IT国产化的核心问题去 IOE&…

【笔试强训】day9

1.添加逗号 思路&#xff1a; 没思路 代码&#xff1a; #define _CRT_SECURE_NO_WARNINGS 1 #include <iostream> #include<string> #include<algorithm> using namespace std;int main() {string a;cin >> a;string ans;int p 1;for (int i a.si…

大模型-入门小知识

大模型是什么 大量参数&#xff08;上亿&#xff09;深度学习模型 人工只能包含机器学习&#xff0c;深度学习,深度学习包括大模型 单个神经元的计算模型&#xff1a; 大模型是怎么训练的 之前是算法&#xff08;神经网络&#xff09;----> 训练&#xff08;门槛降低&…

【IR 论文】Google 对通过 prompt LLM 做 Query Expansion 的工作

论文&#xff1a;Query Expansion by Prompting Large Language Models ⭐⭐⭐ Google Research, arxiv:2305.03653 论文速读 之前我在论文笔记 Query2doc 中介绍了信息检索&#xff08;IR&#xff09;以及 Query Expansion 的相关背景知识。 本篇文章是 Google 发表的关于对…

【NUCLEO-G071RB】005——RCC-PLL时钟配置

NUCLEO-G071RB&#xff1a;005——RCC-PLL时钟配置 设计目标芯片配置程序修改仿真测试 设计目标 将HSI通过PLL倍频到64MHz&#xff0c;并作为系统时钟。 芯片配置 切换到Clock Configuration选项卡&#xff0c;以图形化界面配置时钟。System Clock Mux是CPU核心的时钟源选择…

QT初识

通过图形化界面输出helloworld 既然学习了QT&#xff0c;那么自然要做经典的输出helloworld字符串的实验。 QT有两好几种方案输出helloworld&#xff0c;一种是通过图形化界面输出&#xff0c;一种是通过代码实现。 这里先了解图形化界面的方案。 创建项目后&#xff0c;点…

小米一面:说说MVC与设计模式的关系

前言 大家好&#xff0c;我叫阿杆&#xff0c;不叫阿轩。 先来看看面试环节吧。 面试官&#xff1a;请说说MVC模式是基于哪种设计模式的&#xff1f; 求职者&#xff1a;MVC本身不就是一种设计模式吗&#xff1f; 面试官&#xff1a;我的意思是&#xff0c;MVC是基于23中设计…

考研数学|武忠祥强化课VS张宇强化课(全面对比)

在我看来&#xff0c;这两个老师都很好&#xff0c;选者任何一个都不会踩坑&#xff01; 区别就是&#xff0c;这两个老师属于不同的打法&#xff01; 张宇老师属“仙人指路”型&#xff0c;他会在强化课程&#xff0c;把各种类型的习题总结在一起&#xff0c;然后给学生讲清…

docker内实现多机多卡分布式训练

docker内实现多机多卡分布式训练 1. 多台docker宿主机网络配置2. 创建overlay 网络3. 注意 1. 多台docker宿主机网络配置 https://docs.docker.com/network/overlay/ 这里需要创建overlay网络使得多台宿主机的容器可以通过网络连接 初始化swarm集群&#xff0c;并设置主节点&a…

C语言实现扫雷游戏完整实现(上)

文章目录 前言一、新建好头文件和源文件二、实现游戏菜单选择功能三、定义游戏函数四、初始化棋盘五、 打印棋盘函数六、布置雷函数七、玩家排雷菜单八、标记功能的菜单九、标记功能菜单的实现总结 前言 C语言从新建文件到游戏菜单&#xff0c;游戏函数&#xff0c;初始化棋盘…

鸿蒙OpenHarmony【小型系统运行案例】 (基于Hi3516开发板)

运行 启动系统 在完成Hi3516DV300的烧录后&#xff0c;还需要设置BootLoader引导程序&#xff0c;才能运行OpenHarmony系统。 在Hi3516DV300任务中&#xff0c;单击Configure bootloader&#xff08;Boot OS&#xff09;进行配置即可。 说明&#xff1a; DevEco Device Tool…

Leecode125. 验证回文串

文章目录 概要分析整体架构流程小结 概要 提示&#xff1a;这里可以添加技术概要 如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后&#xff0c;短语正着读和反着读都一样。则可以认为该短语是一个 回文串 。 字母和数字都属于字母数字字符。 给你一个字符…

Java线程技术难点

文章目录 Java线程技术涵盖了许多关键概念和复杂机制&#xff0c;其中一些难点包括但不限于以下几个方面&#xff1a; 线程生命周期管理&#xff1a; 状态转换&#xff1a;理解线程的五种基本状态&#xff08;新建、就绪、运行、阻塞、死亡&#xff09;&#xff0c;以及状态之间…

C语言学习/复习30--结构体的声明/初始化/typedef改名/内存对齐大小计算

一、自定义数据类型 二、结构体 1.结构体的定义&#xff08;与数组相对比&#xff09; 2.结构体全局/局部变量的定义 3.typedef对结构体改名 4.匿名结构体类型的声明 注意事项1&#xff1a; 匿名后必须立即创建结构体变量 、 5.结构体与链表节点定义 注意事项1&…

ASP.NET教务管理平台-权限及公共模块设计与开发

摘 要 随着教育改革的不断深化&#xff0c;高等院校的建设与发展对国民整体素质的提高起着越来越重要的作用&#xff0c;建立一套能够适应这些改变的行政管理方案也就显得尤为重要。对于教务处来说&#xff0c;将信息技术用于校务管理中便是迫切的要求。 教务系统中的用户…

黑马Minio(对象存储服务MinIO)

3.1 MinIO简介 MinIO基于Apache License v2.0开源协议的对象存储服务&#xff0c;可以做为云存储的解决方案用来保存海量的图片&#xff0c;视频&#xff0c;文档。由于采用Golang实现&#xff0c;服务端可以工作在Windows,Linux, OS X和FreeBSD上。配置简单&#xff0c;基本是…