首页 > 其他分享 >Unity Scriptable Object概述

Unity Scriptable Object概述

时间:2024-02-09 09:04:48浏览次数:26  
标签:ScriptableObject Object Scriptable Unity 实例 UI 我们

如何理解Scriptable Object

Scriptable Object是一种数据容器(data container),通常被用来存储大量的数据,并且不依赖于类实例。换句话说,Scriptable Object本身就是一个存放数据的实例。Scriptable Object没有继承自MonoBehavior,而是继承自Scriptable Object,所以Scriptable Object不能当脚本挂载到GameObject上,也不能进行GetComponent等对GameObject的操作,同时Scriptable Object以Asset文件存储,但不论是MonoBehavior还是Scriptable Object最终都继承自Unity Object。

但要注意的是,虽然Scriptable Object没有继承自MonoBehavior,并且他是一种资源文件,但是Scriptable Object始终是以C#代码脚本的形式来编辑的,所以只要不涉及到MonoBehavior继承下来的操作,我们可以编写任何代码来实现我们的想要的功能。

那么接下来就介绍Scriptable Object的基本操作以及几种最常用的用法。

创建Scriptable Object Asset文件

首先像创建脚本一样创建一个C#脚本,打开后把类名后的继承的MonoBehavior改为Scriptable Object,这样我们就创建一个最简单的Scriptable Object的模板,之所以称之为模板,那是因为其以C#脚本的形式存储,我们还不能使用它。我们需要实例化一个继承自Scriptable Object的C#脚本,为了方便在Unity Editor中实例化一个Scriptable Object,我们在脚本类声明前添加CreateAssetMenu属性,这样我们就可以在Unity Asset面板中右键创建一个Scriptable Object实例了,如下图。
image
当我们实例化一个Scriptable Object脚本之后,我们就可以发现实例化后的Scriptable Object脚本的图标变了。
image
我们点击这个实例化后的Scriptable Object Asset文件,在Inspector中我们可以看到在Scriptable Object脚本中声明的public变量,同时我们还可以在Inspect面板中对其进行数据编辑,这个时候我们编辑的数据会被直接以Asset的文件形式保存在磁盘中,同时我们在开始游戏后的对其数据的更改会被永久保存。根据这个特性,我们可以使用Scriptable Object来实现一个简单的游戏存档功能。当然,对于一些不希望被的改变的数据来说,将其设置为私有变量,再通过公有变量进行GetSet操作,或者直接设置为只读类型的变量都可以防止数据被修改。

对于一个Scriptable Object实例,我们可以在其他脚本中访问它,只需要声明一个ScriptableObject类型的变量,再在editor的inspector面板中将我们需要的ScriptableObject实例拖拽赋值就可以在脚本中访问这个ScriptableObject实例了。
image
image
值得注意的是,我们声明时使用的变量名称是我们ScriptableObject模板的类名。

有些时候我们希望每一个在运行时实例化的GameObject都能有一个ScriptableObject来记录自身变量的值,那么这个时候就不能依靠拖拽赋值的方法了,并且如果我们将ScriptableObject实例设置到Prefab中,那么这个Prefab的实例所访问的ScriptableObject其实都来自于同一个ScriptableObject实例。所以针对这个问题,我们可以使用Instantiate方法(或者直接使用ScriptableObject.CreateInstance)来实例化一个ScriptableObject实例,这样我们在不同的实例当中对ScriptableObject的操作都只是其实例化的副本,使用并不会对原始数据产生修改,并且每个实例都有自己的一个ScriptableObject实例了。(最后记得要有Destroy的好习惯)
image

Scriptable Object常用用法之enum

我们在使用enum的时候通常会遇到的问题是,对于enum的修改往往牵扯到很多部分的代码也需要修改,并且enum不支持记录更多的数据。而ScriptableObject则可以在当做是enum使用的情况下记录额外的信息。更多的信息请看Scriptable Object 1 | Enum | Unity3D开放项目

Scriptable Object常用用法之Data

使用ScriptableObject来分离存储数据再适合不过了,假如一个player有几个字段记录了当前血量、最大血量、攻击力等等数据,一般来讲我们都会把这几个字段都写到MonoBehavior里,如果游戏当中我们想让UI反映玩家的血量情况我们应该怎么做?我们也许会选择让玩家保有一个UI的引用,在玩家血量发生修改时通知UI进行修改,或者在UI当中保有玩家的引用,当检测到玩家的血量发生修改的时候就更新UI的状态,又或者我们不希望玩家和UI有这种耦合关系,我们会使用一个Manager脚本来管理二者之间的行为,但是这样会徒增工作量并且加大了项目的复杂程度,项目小的时候这种缺点还不明显,但是一旦项目体积开始变大后这种缺点就很明显了。

所以,这个时候我们可以合理使用ScriptableObject来将一些需要在不同脚本之间传递的数据进行统一管理,这个时候我们就抽象出了数据层,再让玩家和UI保有这个ScriptableObject的引用,玩家修改ScriptableObject中的值后,UI也能够知道值被修改了从而做出修改,但此时玩家和UI双方都不知道对方的存在,就实现了解耦。并且,此时写在ScriptableObject中的数据是可以在Inspector面板中修改的,相比于在场景Hierarchy面板中找到对象再修改的方式,这无疑要直观方便的多,特别是项目复杂了过后。

当然,上述情景是一个最简单的应用场景,对于一些稍微复杂一点的项目来说,ScriptableObject也有一定的局限性,所以要充分分析项目的需求,在合适的地方使用ScriptableObject。更多的信息请看Scriptable Object 2 | Data | Unity3D开放项目

Scriptable Object常用用法之Runtime Set

RuntimeSet也就是运行时集,比如在游戏运行时游戏内的所有敌人就是一个运行时集,有些情况下我们需要得到这个RuntimeSet来对所有集合内的object做统一的处理,那么ScriptableObject就是运来存放运行时集RuntimeSet的最佳选项,我们只需要让需要的object在被生成时将自己注册进存放进ScriptableObject所做的RuntimeSet中,就可以在任何地方访问到这个RuntimeSet,当然前提就是我们需要在代码中获得这个ScriptableObject的引用即可。更多信息请看Scriptable Object 5 | Runtime Set | Unity开放项目

Scriptable Object常用用法之Editor拓展

Scriptable Object 3 | Editor扩展 | Unity3D开放项目

END

最后再说一点,ScriptableObject最终最合适的用法还是作为一个数据容器来使用,我们不能指望ScriptableObject能够做到更多。ScriptableObject能够帮助我们解决一些代码之间的耦合,独立出一些数据和逻辑存放在ScriptableObject中,就可以变成可拔插式的SO文件,随便组合,就能组装出较为灵活配置的AI系统。

ScriptableObject不能用做数据文件最终存储的载体

标签:ScriptableObject,Object,Scriptable,Unity,实例,UI,我们
From: https://www.cnblogs.com/HalfDog/p/18012289

相关文章

  • C#对window 硬件类操作 ManagementObjectSearcher
    在解决方案--引用--右键--添加引用---程序集---框架---勾选System.Management 前言: 我们在很多情况下想要获得计算机的硬件或操作系统的信息,比如获得CPU序列号给自己的软件添加机器码锁绑定指定电脑。又或者想要获得硬盘分区,声卡显卡等信息。开篇:我们用到的主要类是Managem......
  • NuGetForUnity用不了时的一个折衷方案
    如果NuGetForUnity网络访问不了或者下载速度非常慢,导致无法正常使用,那可以试试下面的方法。 1)先用vs的NuGet包管理器下载,vs下貌似没遇到网络问题,下载很快 注意,vs不是下载在Unity的Assets文件夹下的,而是和他同层级,所以此时Unity并不会加载所下载的dll文件的 2)然后......
  • Unity Navigation导航系统
    一、Navigation导航系统基本介绍Navigation导航系统是unity的寻路组件,将静态或动态的复杂场景烘焙简化为简单的(NavMesh)导航网格用于AI寻路计算。值得注意的是,这个组件的NavMesh系统存在一些性能和使用场景上的缺陷,如很难在运行时修改navmesh、场景过大会造成内存上的开销,以及不支......
  • Unity接入 KimiChat 代码示例
    代码usingSystem.Runtime.CompilerServices;usingSystem.Threading.Tasks;usingUnityEngine;usingUnityEngine.Networking;publicclassTestKimi:MonoBehaviour{privatestringapiKey="YourKey";//替换为你的API密钥privatestringapiUrl=......
  • 限制Unity帧率的方式
    1)限制Unity帧率的方式2)只在编辑器内,纹理不开启Read&Write情况下,如何获取纹理所有颜色值3)如何在FBX剔除Lit.shader依4)如何在iPhone12mini设备上禁止竖屏这是第373篇UWA技术知识分享的推送,精选了UWA社区的热门话题,涵盖了UWA问答、社区帖子等技术知识点,助力大家更全面地掌握和学习......
  • 【Unity】记一次卡顿优化(由3D资源面数过多引起)
    这个优化方法可能仅对我有效,我只是做一个记录条件:模型很大,并且shader中使用了Smoothness优化方法打开Mesh引用的模型修改模型Normal为calculate修改SmoothnessSource为fromAngle修改SmoothingAngle降到你可以接收的值,我设置的是20。在unity文档中说的是,通常SmoothingAn......
  • Unity Mono单例(MonoSingleton)C#脚本
    什么是单例模式?单例模式是设计模式的一种,一般来说,使用单例模式的类,在程序中全局只会存在一个实例,并且一般来讲其是全局可被访问的。在unity游戏开发中,单例模式广泛应用于GameManager和各种Controller这种只需要一个实例的脚本。以下就是UnityMono单例的泛用脚本usingSystem.......
  • Unity打包Android报错:Target Android SDK not installed Android SDK does not includ
    1.需要查看当前unity版本中安装的SDKVersion2.找到对应路径下的文件,打开build-tools文件,其中就是对应的SDKVersion4.修改Unity中对应的配置 ......
  • Unity Animation动画系统概述
    一、UnityAnimation动画系统基本介绍unity提供了一套非常强大灵活且成熟的动画系统,不论是2d还是3d动画都有相应的组件和接口提供给开发者使用,不过这篇文章主要还是讲解3D部分的动画系统。我们在游戏开发时时常需要角色动起来,除了位置上的移动之外,我们还需要匹配角色的行为或玩......
  • Unity 基于群体寻路的解决方案
    群体寻路是一种模拟群体行为的技术,它使得游戏中的角色能够以一种有组织的方式移动。在群体中,每个角色都有自己的目标位置,并且会根据周围的情况决定如何移动。群体寻路可以帮助我们实现一些有趣的场景,比如鸟群飞行、鱼群游动等。在Unity中实现群体寻路,我们可以使用NavMeshAgent组......