当前位置:   article > 正文

Unity ScriptableObject 使用方法详解

unity scriptable

概述:

ScriptableObject类直接继承自Object类;它和MonoBehaviour是并列的,都继承自Object(但MonoBehaviour并不是直接继承自Object);

ScriptableObject 就是一个数据容器,可以用来存储大量的数据,它是可序列化的,这个特点也正决定了它的主要用途;一个主要用处就是通过将数据存储在ScriptableObject对象中来减少工程以及游戏运行时因拷贝值所造成的内存占用;

ScriptableObject与预制体:
当你有一个预制体,它附加了一些mono脚本,包含了一些数据,每次我们实例化预制体的时候它都会 拷贝 assets下原预制体的值生成一份自己的拷贝,然后我们可以修改场景内预制体的值而并不影响assets下预制体的值,这是prefab的特性,对于我们从一个prefab模板生成属性不同的游戏对象是很有用的,但是如果prefab里的脚本数据是不需要修改的,它就会造成很大的资源浪费,尤其在数据很多的时候;为了避免这种问题,我们可以在不需要修改prefab里的脚本数据时,考虑使用ScriptableObject来存储这些重复的数据,然后其它所有预制体都可以使用引用的方式来访问这份数据,这就意味着不管场景中实例了多少预制体,在内存中就只需要有一份数据;它所带给我们的启示就是,当预制体中的脚本里有大量重复数据时,我们要想着将数据抽离,单独保存在本地;

举一个子弹的例子:

1、我们要先做一个子弹的预制体,为了体现它的属性,我们会写一个派生自MonoBehaviour的脚本Bullet,在里面添加一些属性,然后将其附加到一个子弹游戏对象上,完成了一个子弹预制体的制作;
2、在场景中实例化新的子弹的时候,这个实例也会有一个Bullet实例,而且最重要的是这些子弹都会有这样一份Bullet而且它们的数据是相同的,这就是之前讲到的因为拷贝值产生新的实例导致了大量的内存占用;
3、我们这个时候我们就可以把这个派生自MonoBehaviour的脚本里的数据放置在派生自ScriptableObject的脚本,然后就可以在创建Assets下创建一份数据文件,设置完数据后,在Bullet中我们就定义一个指向ScriptableOjbect对象的引用,这样它就由原来的拷贝大量值并存储重复的值变成了拷贝一个引用并存储一个引用;

应用场景及方式
当使用编辑器运行游戏的时候,可以将数据保存到ScriptableObject里(当创建一个脚本化对象实例后使用AssetDatabase.CreateAsset()保存该资源),退出之后也不会丢失,因为它是作为Assets下的资源存在的;它是仅在编辑器中才可以保存修改的数据(因为ScriptableObject对象虽然声明在UnityEngine中,但是它的Scriptable是通过UnityEditor命名空间下的类例如Editor类等来实现的),所以在部署构建的时候不可以用于存储游戏运行时更改的数据,但是可以使用之前存储好的数据,也就是ScriptableObject生成的数据资源文件在Editor外具有只读属性,这是非常需要注意的一点,如果你需要在游戏中修改数据并存储下来,就不推荐使用ScriptableObject了;

总结:
它就是用来在编辑器模式下保存和存储数据到本地Assets下的,数据保存以后是可以共享的,就像纹理、shader等资源一样,是可以共享于当前整个工程和其它工程的;这个ScriptableObject在真机上不可修改的,就像我们不可以在游戏运行时修改一个shader资源的代码、不可以修改一个纹理资源的像素内容一样,而在Unity Editor里可以修改ScriptableObject是因为Unity的编辑器对它格式的支持,就像使用vs code修改shader和使用ps修改一张纹理一样;

ScriptableObject的特点

  • ScriptableObject 数据存储在 asset 资源文件中,类似 unity 材质或纹理资源
  • ScriptableObject 资源在实例化时是被引用,而非像 Prefab 或其他 GameObject 一样是复制(实际场景中会存在多个 GameObject),所有 ScriptableObject 可以节省 memory

基本使用

using UnityEngine;

[CreateAssetMenu(menuName="MySubMenue/Create ScritableTest")]
public class ScritableTest: ScriptableObject
{
    public int someVariable;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

其中,[CreateAssetMenu(menuName="MySubMenue/Create MyScriptableObject ")]可以让我们在资源创建菜单中添加创建这个ScriptableObject的选项,类似创建脚本、材质等其他资源。

我们也可以在脚本中动态创建一个ScriptableObject:

ScriptableObject.CreateInstance<ScritableTest>();
  • 1

这会在内存中创建一个新的实例,用作临时修改等用途,然后在不使用的时候可以让GC回收。其中MyScriptableObject 是自定义的类型,并继承于ScriptableObject

保存创建的数据:

  var test = ScriptableObject.CreateInstance<ScritableTest>();
  Debug.Log(test.someVariable);

  string fullPath = "Assets/TestData.asset";
  AssetDatabase.CreateAsset(test, fullPath);
  AssetDatabase.Refresh();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

在这里插入图片描述
加载数据
可以将保存的文件放在Resources文件夹中,然后使用Resources.LoadAll去加载,当然还有很多其他加载方式。

 var preferencesFiles = Resources.LoadAll<ScritableTest>("TestData");
   if(preferencesFiles.Length == 0)
   {
       Debug.Log("null");
   }
   else
   {
       Debug.Log(preferencesFiles[0].someVariable);
   }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/112502
推荐阅读
相关标签
  

闽ICP备14008679号