unity——ScriptableObject相关知识点【学习笔记/不足之处欢迎斧正/个人复习向/侵删】

一、相关简介

1.ScriptableObject是什么:Unity提供的一个数据存储基类

2.ScriptableObject的好处有哪些:文件配置、数据复用、更好的处理数据带来的多态性为

二、ScriptableObject的创建

1.自定义ScriptableOject数据容器

        继承ScriptableObject类

        在该类中声明成员(变量、方法等)

public class StudyUnity : ScriptableObject
{//可以在其中声明任何一种类型的变量,//如果想要在Inspector窗口中能够编辑它,那么//声明变量的规则应该与MonoBehavior的public变量规则相同public bool a;public float b;public GameObject c;public Material d;
}

        通过这种方式,我们能在Inspector窗口中看到变化,其中数据的关联信息是通过脚本文件unity配置的meta文件进行记录的,之后我们可以利用他的信息创建对应的数据资源文件

2.根据自定义ScriptableObject数据容器创建数据文件

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

具体的方式有两种:

        1.为类添加CreateAssetMenu通过菜单创建资源特性:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;[CreateAssetMenu(fileName ="a文件",menuName ="b菜单",order =0)]public class StudyUnity : ScriptableObject
{//可以在其中声明任何一种类型的变量,//如果想要在Inspector窗口中能够编辑它,那么//声明变量的规则应该与MonoBehavior的public变量规则相同public bool a;public float b;public GameObject c;public Material d;
}

这时我们回到unity可以看到

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

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;public class Study2
{[MenuItem("a/Tostudy")]//using UnityEditor;public static void ToStudy(){}
}

在此之后,回到unity中我们可以看到:

我们只需要在静态函数中数次额创建资源文件的代码即可

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;public class Study2
{[MenuItem("a/ToStudy")]//using UnityEditor;public static void ToStudy(){StudyUnity s=ScriptableObject.CreateInstance<StudyUnity>();//通过编译器API,可以根据数据创建一个数据资源文件AssetDatabase.CreateAsset(s, "Assets/Studt2data.asset");//在Assets路径下创建Studt2data.asset//保存创建的资源AssetDatabase.SaveAssets();//刷新界面AssetDatabase.Refresh();}
}

3.使用ScriptableObject的好处体现在哪里?

        可以更方便的配置数据,可以直接在Inspector中进行数据的配置

        可以在项目之间进行复用,可以拷贝继承ScriptableObject的脚本到任何工程之中

三、ScriptableObject数据文件

        1.ScriptableObject如何使用:

                通过Inspector窗口中的public变量进行关联:可以用上述方法创建数据文件,同时在继承MonoBehaviour类中申明数据容器类型的成员,最后在Inspector窗口中进行关联

                通过资源加载的信息关联:加载数据文件资源,需要注意的是,Resources\AB包、Addressables都支持加载继承ScriptableObject的数据文件(如果同时有多个对象关联同一个数据容器文件,他们贡献的是一个对象,因为是引用对象,所以在任何地方进行修改后,其他地方也会发生改变)

        2.ScriptableObject的生命周期函数

                类似于MonoBehavior,但是ScriptableObject的生命周期函数更少

                Awake 数据文件创建时调用

                OnDestroy对象将要被销毁时调用

                OnDisable对象销毁时,即将重新把加载脚本程序集时调用

                OnEnable创建或者加载对象时调用

                Onvalidate 编译器才会进行调用的生命周期函数,Unity在加载脚本或者Inspector窗口中更改值时调用

        3.使用的好处:

                通过代码修改对象中的内容后,会影响到数据文件,相当于达到了编译器中数据持久化的目的,注意该数据持久化,只会在编译模式下持久,发布运行时并不会保留数据;同时,如果多个对象关联了同一个数据文件,相当于他们服用了一组数据,更加节约内存

四、非持久数据

        1.非持久化数据指的是什么:不管是编辑器模式还是发布后都不会持久化的数据,我们可以根据需求随时创建对应数据对象进行使用,,如同直接new一个数据结构类对象一样

        2.如何利用ScriptableObject生成非持久化的数据:利用ScriptableObject中的静态方法CreateInstance<>(),该方法可以运行时创建出指定继承ScriptableObject的对象,且该对象只存在于内存当中,可以被GC,每调用一次便创建一次

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Study4 : MonoBehaviour
{public StudyUnity studyUnity;void Start(){//为了不想要数据持久化,不加载数据资源文件studyUnity = ScriptableObject.CreateInstance<StudyUnity>();studyUnity=ScriptableObject.CreateInstance("Studyunity") as StudyUnity;//创建出来的对象是一个基类对象,父类装子类,需要as//以上方式创建出来的对象,它的默认值不会受到脚本中设置的影响}//studyUnity = ScriptableObject.CreateInstance<StudyUnity>();//会发生报错}

        3.ScriptableObject非持久化数据存在的意义:

                如果希望在运行时能有一组唯一的数据可以使用,但是这个数据又不太希望保存为数据资源文件浪费空间,那么非持久化数据的好处便可以体现,其特点为:只是在运行时使用,在编辑器模式下也不会保存在本地(停止运行后,数据便会丢失)

五、如何让其拥有真正意义上的持久

        数据持久化本质上是读取硬盘上的内容到内存当中,需要的时候将内存当中的内容存储到硬盘上,游戏退出程序关闭后,数据信息就会被储存在硬盘上,达到持久化的目的

        持久化一般采用 PlayerPrefs/XML/Json/2进制的方式

        实际上ScriptableObject并不适合用来做数据持久化的功能,但我们可以利用学过的数据持久化方案令其持久化

        例如利用Json

                   存储数据:

studyData.i=10086;
studyData.f=8.8f;
studyData.b=false;string str=JsonUtility.ToJson(studyData);File.WriteAllText(Application.persistentDataPath+"/test.json",str);
//File需要引用命名空间

                   读取数据:

string str =File.ReadAllText(Application.persistentDataPath+"/test.json");
//反序列化数据文件

                   从本地读取Json字符串,根据json字符串反序列化出数据,将内容覆盖到数据对象之中

JsonUtility.FromJsonOverwrite(str,data);

             实际上,使用ScriptableObject来做持久化并非是好的选择,更有一种画蛇添足的意思

六、 使用ScriptableObject来配置数据

        为什么要使用ScriptableObject数据文件来作配置文件?

        配置文件的数据在游戏发布之前便已经定好了规则,配置数间的数据在游戏运行时只会读出来使用,并不会改变其内容。同时在untiy的Inspector窗口进行配置更加的方便(不需要使用第三方软件)

适用范围:只用不改,经常配置的数据,例如untiy内置的技能编译器,关卡编译器等(内置编译器只会在编译模式下进行,编译模式下ScriptableObject具备数据持久化的特性)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;[CreateAssetMenu(fileName = "StudyInfo",menuName ="ScriptableObject/信息")]
public class StudyInfo : ScriptableObject
{//自定义类型想要可编辑,需要添加下行代码[System.Serializable]public class StudyData{public string Name;public string Description;}public List<StudyData> studyList;
}

之后回到unity,在窗口创建后,我们可以看到

        

想获取以此法创建出来的数据,可以在一个脚本中创建一个对应对象,将脚本挂载到物体上进行关联,便可以获取到对应数据

七、使用ScriptableObject来复用数据

        使用预设体可能存在内存浪费,例如创建一个子弹,其速度是相同的,但是在实际上子弹速度在每次创建时都要占用一定内存(只用不变的数据)

        对于不同的对象,使用相同的数据,可以使用ScriptableObject节约内存(即使游戏被发布,也是使用一块内存空间)

八、数据带来的多态性为

        某些行为的变化是因为数据的不同带来的,我们可以利用面向对象的特性和原则,以及设计模式的知识点,结合ScriptableObject做出更方便的功能,比如随机音效(利用里氏替换和依赖倒转原则),物品拾取和AI等

例如

        

public  abstract class AudioPlayBase : ScriptableObject
{public abstract void Play(AudioSource source);}

          

[CreateAssetMenu()]
public class RandomPlay : AudioPlayBase
{public List<AudioClip> clips;//随机播放的音效文件public override void Play(AudioSource source){if (clips.Count == 0) return;//设置音效切片文件source.clip = clips[Random.Range(0,clips.Count)];//进行播放source.Play();}}

九、单例模式化的数据获取

        对于只用不变并且要复用的数据,我们往往要在很多地方获取他们,如果我们直接在public关联或者动态加载。如果多处使用,会存在多处重复代码,开发效率较低。如果我们将此类数据通过但理论模式化的去获取,可以提升效率,减少代码量

        实现ScriptableObject数据单例模式基类:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class SingleScriptableObject<T>:ScriptableObject where T:ScriptableObject
{private static T instance;//数据基类,不能直接去newpublic static T Instance {get { if(instance == null){//如果为空,首先去资源路径下加载对应的数据资源文件instance=Resources.Load<T>("ScriptableObject/" + typeof(T).Name);//Load需要继承Object类,由于ScriptableObject已经继承过了//因此只需补充where T:ScriptableObject即可}//防止没有这个文件从而发生错误if(instance == null){instance = CreateInstance<T>();}//甚至可以在这里 从json当中读取数据return instance;}}}

        

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

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

相关文章

Web后端开发:登录认证案例

登录功能 需求分析 在登录界面中&#xff0c;输入用户的用户名以及密码&#xff0c;然后点击 “登录” &#xff0c;服务端判断用户输入的用户名和密码是否都正确。如果正确&#xff0c;则返回成功结果&#xff0c;前端跳转至系统首页面&#xff1b;否则报错&#xff0c;停留在…

【Web】vulhub Shiro-550反序列化漏洞复现学习笔记

目录 Shiro简介 复现流程 工具一把梭 半脚本半手动 原理分析 反序列化入口 常见的key 登录过程 验证过程 利用原理 Shiro简介 Apache Shiro 是一个强大且易于使用的 Java 安全框架&#xff0c;用于身份验证、授权、加密和会话管理等安全功能。Shiro 的设计目标是简单…

2.0 Zookeeper 安装配置

Linux 安装 zookeeper 下载地址为: Apache ZooKeeper。 选择一稳定版本&#xff0c;本教程使用的 release 版本为3.4.14&#xff0c;下载并安装。 打开网址 https://www.apache.org/dyn/closer.lua/zookeeper/zookeeper-3.4.14/zookeeper-3.4.14.tar.gz&#xff0c;看到如下界…

通过平扫CT实现胰腺癌早筛(平扫CT+AI)

Large-scale pancreatic cancer detection via non-contrast CT and deep learning - PubMed (nih.gov) 实验团队&#xff1a;海军军医大学第一附属医院&#xff08;上海长海医院&#xff09;&#xff0c;放射诊断科曹凯主治医生为共同第一作者&#xff0c;邵成伟、陆建平等教…

自然语言学习nlp 六

https://www.bilibili.com/video/BV1UG411p7zv?p118 Delta Tuning&#xff0c;尤其是在自然语言处理&#xff08;NLP&#xff09;和机器学习领域中&#xff0c;通常指的是对预训练模型进行微调的一种策略。这种策略不是直接更新整个预训练模型的权重&#xff0c;而是仅针对模型…

第七届西湖论剑·中国杭州网络安全技能大赛 AI 回声海螺 WP

第七届西湖论剑中国杭州网络安全技能大赛-AI-回声海螺 开题&#xff0c;提示输入密码给FLAG。 这个回声海螺应该是个AI&#xff0c;就是复读机&#xff0c;应该是想办法从中骗出密码。 感觉这题不像是AI&#xff0c;也没用啥模型&#xff0c;应该是WEB。或者是说类似于AI的提示…

150基于matlab的凸轮轮廓的设计计算与绘图计算此结构的最优化参数

基于matlab的凸轮轮廓的设计计算与绘图计算此结构的最优化参数&#xff0c;根据其原理输出推程和回程的最大压力角、最小曲率半径等相关结果。程序已调通&#xff0c;可直接运行。 150 凸轮轮廓的设计 结构的最优化参数 (xiaohongshu.com)

uniapp vue3怎么调用uni-popup组件的this.$refs.message.open() ?

vue2代码 <!-- 提示信息弹窗 --><uni-popup ref"message" type"message"><uni-popup-message :type"msgType" :message"messageText" :duration"2000"></uni-popup-message></uni-popup>typ…

OpenEuler20.03LTS SP2 上安装 OpenGauss3.0.0 单机部署过程(二)

开始安装 OpenGauss 数据库 3.1.7 安装依赖包 (说明:如果可以联网,可以通过网络 yum 安装所需依赖包,既可以跳过本步骤。如果网络无法连通,请把本文档所在目录下的依赖包上传到服务器上,手工安装后,即无需通过网络进行 Yum 安装了): 上传:libaio-0.3.111-5.oe1.x8…

C语言的循环结构

目录 前言 1.三种循环语句 1.while循环 2.for循环 2.1缺少表达式的情况 3.do while循环 2.break语句和continue语句 2.1在while循环中 2.2在for循环中 2.3在do while 循环中 3.循环的嵌套 4.go to语句 前言 C语⾔是结构化的程序设计语⾔&#xff0c;这⾥的结构指的是…

《MySQL 简易速速上手小册》第4章:数据安全性管理(2024 最新版)

文章目录 4.1 用户认证和权限控制4.1.1 基础知识4.1.2 重点案例&#xff1a;使用 Python 管理 MySQL 用户权限4.1.3 拓展案例 4.2 防止 SQL 注入和其他安全威胁4.2.1 基础知识4.2.2 重点案例&#xff1a;使用 Python 和 MySQL 进行安全的数据查询4.2.3 拓展案例 4.3 数据加密和…

【Java八股面试系列】JVM-内存区域

目录 Java内存区域 运行时数据区域 线程独享区域 程序计数器 Java 虚拟机栈 StackFlowError&OOM 本地方法栈 线程共享区域 堆 GCR-分代回收算法 字符串常量池 方法区 运行时常量池 HotSpot 虚拟机对象探秘 对象的创建 对象的内存布局 句柄 Java内存区域 运…

Golang与Erlang有什么差异

Golang和Erlang是两种备受关注的编程语言&#xff0c;它们各自具有独特的特点和优势。下面我将简单的探讨一下Golang和Erlang之间的差异&#xff0c;并且分析它们在并发模型、运行环境、函数式编程和领域特性等多个方面的不同之处。 并发模型 Golang使用goroutines和channels…

UE4运用C++和框架开发坦克大战教程笔记(十九)(第58~60集)完结

UE4运用C和框架开发坦克大战教程笔记&#xff08;十九&#xff09;&#xff08;第58~60集&#xff09;完结 58. 弹窗显示与隐藏59. UI 面板销毁60. 框架完成与总结 58. 弹窗显示与隐藏 这节课我们先来补全 TransferMask() 里对于 Overlay 布局类型面板的遮罩转移逻辑&#xff…

获取视频帧图片

在实现了minio文件上传的基础上进行操作 一、编写pom <dependency><groupId>org.jcodec</groupId><artifactId>jcodec</artifactId><version>0.2.5</version> </dependency> <dependency><groupId>org.jcodec<…

【RPA】智能自动化的未来:AI + RPA

伴随着人工智能&#xff08;AI&#xff09;技术的迅猛进步&#xff0c;机器人流程自动化&#xff08;RPA&#xff09;正在经历一场翻天覆地的变革。AI为RPA注入了新的活力&#xff0c;尤其在处理复杂任务和制定决策方面。通过融合自然语言处理&#xff08;NLP&#xff09;、机器…

Flink面试准备

零. 主要内容 一. Flink 提交 1. Flink怎么提交? Local模式 JobManager 和 TaskManager 共用一个 JVM,只需要jdk支持&#xff0c;单节点运行&#xff0c;主要用来调试。 Standlone模式 Standlone 是Flink自带的一个分布式集群&#xff0c;它不依赖其他的资源调度框架、不依赖y…

leetcode——滑动窗口题目汇总

本章总结一下滑动窗口的解题思路&#xff1a; 在字符串中使用双指针 left 和 right 围成的一个左闭右开的区域作为一个窗口。不断将 right 向右滑动&#xff0c;直到窗口中的字符串符合条件。此时将 left 向右滑动&#xff0c;直到窗口中的字符串不符合条件&#xff0c;期间需…

离线场景下任意文档的在线预览及原样格式翻译,不依赖其他厂商接口非侵入式一行js代码实现网站的翻译及国际化,可配置使用多种翻译语言

离线场景下任意文档的在线预览及原样格式翻译&#xff0c;不依赖其他厂商接口非侵入式一行js代码实现网站的翻译及国际化&#xff0c;可配置使用多种翻译语言。 要实现翻译需要解决以下3个主要问题&#xff1a; 1&#xff09;from&#xff1a;内容本身的语言类型是什么&#xf…

PCIE 参考时钟架构

一、PCIe架构组件 首先先看下PCIE架构组件&#xff0c;下图中主要包括&#xff1a; ROOT COMPLEX (RC) (CPU); PCIE PCI/PCI-X Bridge; PCIE SWITCH; PCIE ENDPOINT (EP) (pcie设备); BUFFER; 各个器件的时钟来源都是由100MHz经过Buffer后提供。一个PCIE树上最多可以有256…