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;

    //数据基类,不能直接去new
    public 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;
        }

    }
    
}

        

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2024/2/7总结

Node.js 什么是node.js node.js是一个基于chrome v8 引擎的 JavaScript 运行环境。 浏览器是JavaScript的前端运行环境node.js是JavaScript的后端运行环境 node.js中无法调用DOM和BOM等浏览器内置API fs模块 是node.js官方提供的、用来操作文件的模块&#xff0c;它提供了一系…

3.1-媒资管理之需求分析+搭建Nacos

文章目录 媒资管理模块1 模块需求分析1.1 模块介绍1.2 业务流程1.2.1 上传图片1.2.2 上传视频1.2.3 处理视频1.2.4 审核媒资 2.2 搭建Nacos2.2.1 服务发现中心2.2.2 配置中心2.2.2.1 配置三要素2.2.2.3配置content-api 2.2.3 公用配置2.2.4 配置优先级2.2.5 导入配置文件2.2.6 …

Java学习笔记------API

API API&#xff08; Application Programming Interface&#xff09;&#xff1a;应用程序编程接口 简单的说&#xff0c;API就是Java里面别人已经写好的东西&#xff0c;不用自己编写&#xff0c;直接使用即可 例如&#xff1a; public static void main&#xff08;Str…

[设计模式Java实现附plantuml源码~行为型]请求的链式处理——职责链模式

前言&#xff1a; 为什么之前写过Golang 版的设计模式&#xff0c;还在重新写Java 版&#xff1f; 答&#xff1a;因为对于我而言&#xff0c;当然也希望对正在学习的大伙有帮助。Java作为一门纯面向对象的语言&#xff0c;更适合用于学习设计模式。 为什么类图要附上uml 因为很…

C#,栅栏油漆算法(Painting Fence Algorithm)的源代码

1 刷油漆问题 给定一个有n根柱子和k种颜色的围栏&#xff0c;找出油漆围栏的方法&#xff0c;使最多两个相邻的柱子具有相同的颜色。因为答案可以是大的&#xff0c;所以返回10^97的模。 计算结果&#xff1a; 2 栅栏油漆算法的源程序 using System; namespace Legalsoft.Tr…

跨境电商新风潮:充分发挥海外云手机的威力

在互联网行业迅速发展的大环境下&#xff0c;跨境电商、海外社交媒体营销以及游戏产业等重要领域都越来越需要借助海外云手机的协助。 特别是在蓬勃发展的跨境电商领域&#xff0c;像亚马逊、速卖通、eBay等平台&#xff0c;结合社交电商营销和短视频内容成为最有效的流量来源。…

百亿规模京东实时浏览记录系统的设计与实现

百亿规模京东实时浏览记录系统的设计与实现 系统介绍 浏览记录系统主要用来记录京东用户的实时浏览记录&#xff0c;并提供实时查询浏览数据的功能。在线用户访问一次商品详情页&#xff0c;浏览记录系统就会记录用户的一条浏览数据&#xff0c;并针对该浏览数据进行商品维度…

【PyTorch][chapter 15][李宏毅深度学习][Neighbor Embedding-LLE]

前言&#xff1a; 前面讲的都是线性降维&#xff0c;本篇主要讨论一下非线性降维. 流形学习&#xff08;mainfold learning&#xff09;是一类借鉴了拓扑流行概念的降维方法. 如上图,欧式距离上面 A 点跟C点更近&#xff0c;距离B 点较远 但是从图形拓扑结构来看&#xff0c; …

通过Harbor构建docker私服仓库

Harbor是一个用于存储和分发Docker镜像的企业级Registry服务器&#xff0c;它扩展了开源的Docker Distribution&#xff0c;通过添加一些企业必需的功能特性&#xff0c;如安全、标识和管理等。Harbor由VMware公司开发并开源&#xff0c;旨在帮助用户迅速搭建一个企业级的Docke…

16:定时器和计数器

定时器和计数器 1、定时器和计数器的介绍2、定时器是如何工作3、寄存器4、51单片机定时器简介&#xff08;数据手册&#xff09;5、定时器中的寄存器&#xff08;数据手册&#xff09;5.1、TCON&#xff08;定时器控制寄存器&#xff09;5.2、TMOD&#xff08;工作模式寄存器&a…

WordPress突然后台无法管理问题

登录WordPress后台管理评论&#xff0c;发现点击编辑、回复均无反应。 尝试清除缓存、关闭CF连接均无效。 查看插件时发现关闭wp-china-yes插件可以解决问题。 后来又测试了下发现加速管理后台这项&#xff0c;在启用时会发生点击无效问题&#xff0c;禁用就好了&#xff0c;不…

Mysql进阶(sql优化和explain关键字)

一、为什么要对SQL进行优化&#xff1f; 由于业务数据量的增多&#xff0c;SQL的执行效率对程序的运行效率影响增大&#xff0c;此时就需要对SQL进行优化。 二、SQL优化的方法 1.查询sql尽量不要使用select * &#xff0c;而是具体字段。 节省资源&#xff0c;减少开销。 …

Flink Format系列(2)-CSV

Flink的csv格式支持读和写csv格式的数据&#xff0c;只需要指定 format csv&#xff0c;下面以kafka为例。 CREATE TABLE user_behavior (user_id BIGINT,item_id BIGINT,category_id BIGINT,behavior STRING,ts TIMESTAMP(3) ) WITH (connector kafka,topic user_behavior…

【01】判断素数/质数(C语言)

目录 &#xff08;1&#xff09;素数特点&#xff1a;只能被1和本身整除 &#xff08;2&#xff09;代码如下&#xff1a; &#xff08;3&#xff09;运行结果如下 ​编辑 &#xff08;4&#xff09;函数引申 &#xff08;1&#xff09;素数特点&#xff1a;只能被1和本身…

飞马座卫星

1960年代马歇尔太空飞行中心的历史显然与建造土星五号月球火箭有关。然而&#xff0c;鲜为人知的是该中心在设计科学有效载荷方面的早期工作。 Fairchild 技术人员正在检查扩展的 Pegasus 流星体探测表面。Pegasus 由马里兰州黑格斯敦的 Fairchild Stratos Corporation 通过马歇…

HarmonyOS SDK 助力新浪新闻打造精致易用的新闻应用

原生智能是HarmonyOS NEXT的核心亮点之一&#xff0c;依托HarmonyOS SDK丰富全面的开放能力&#xff0c;开发者只需通过几行代码&#xff0c;即可快速实现AI功能。新浪新闻作为鸿蒙原生应用开发的先行者之一&#xff0c;从有声资讯入手&#xff0c;基于Speech Kit朗读控件上线听…

Docker-Learn(二)保存、导入、使用Docker镜像

1.保存镜像 根据上一节内容&#xff0c;将创建好镜像进行保存&#xff0c;需要退出当前的已经在运行的docer命令行中断里面&#xff0c;可以通过在终端里面输入指令exit或者按下键盘上的 ctrlD建退出&#xff1a; 回到自己的终端里面&#xff0c;输入指令&#xff1a; docker…

基于全连接神经网络模型的手写数字识别

基于全连接神经网络模型的手写数字识别 一. 前言二. 设计目的及任务描述2.1 设计目的2.2 设计任务 三. 神经网络模型3.1 全连接神经网络模型方案3.2 全连接神经网络模型训练过程3.3 全连接神经网络模型测试 四. 程序设计 一. 前言 手写数字识别要求利用MNIST数据集里的70000张…

05 06 Verilog基础语法与应用讲解

05. 1. 位操作 计数器实验升级&#xff0c;设计8个LED灯以每个0.5s的速率循环闪烁&#xff08;跑马灯&#xff09; 1.1 方法1&#xff1a;使用移位操作符<<来控制led灯的循环亮灭 设计代码 Verilog中&#xff0c;判断操作的时候不加位宽限定是可以的&#xff0c;比如i…

解析spritf和sscanf与模拟常用字符串函数strchr,strtok(二)

今天又来继续我们的字符串函数的文章&#xff0c;这也是最后一篇了。希望这两篇文章能让各位理解透字符串函数。 目录 strchr strtok sprintf和sscanf strchr strchr 是一个用于在字符串中查找特定字符首次出现位置的函数。以下是解析和模拟实现 strchr 函数的示例&…