赞
踩
是Unity提供的一个数据配置存储的基类。可以用来保存大量数据的数据容器,
是一个可以自定义数据的资源文件,一般用来当关卡配置,或者其他的配置一类的文件,一般用于只用不改的公共数据。
可以发现,这个能做的和单例类也能做,单例类也是共享一份数据,有什么区别?
首先,当我们在编辑模式下修改了继承自 ScriptableObject 对象的数据文件内容时,修改的数据将被保存到磁盘上。但是在发布运行后,即使在游戏中修改了 ScriptableObject 的数据,改后的数据并不会保存在本地,重新打开运行时数据并还是配置的初始数据。
这种比较简便,在project文件内,点击加号就能看到,这种方法需要继承ScripteableObject类
在顶部菜单栏创建,自主传入类名,指定生成位置
1、直接声明一个资源类,然后在inspector,直接将asset拖上去
2、放到能加载到的文件夹内,直接加载
3、通过单例模式去加载,这样不用去动态加载和手动拖取
3、数据只会在编辑模式才会被更改,也可以在编辑模式下,运行时候用代码更改,但是不能再打包出去后更改
void Start() { #region 知识点一 ScriptableObject数据文件的使用 //1.通过Inspector中的public变量进行关联 //1-1.创建一个数据文件 //1-2.在继承MonoBehaviour类中申明数据容器类型的成员 // 在Inspector窗口进行关联 //data.PrintInfo(); //2.通过资源加载的信息关联 //加载数据文件资源 //注意:Resources、AB包、Addressables都支持加载继承ScriptableObject的数据文件 data = Resources.Load<MyData>("MyDataTest"); data.PrintInfo(); //注意:如果多个对象关联同一个数据容器文件,他们共享的是一个对象 // 因为是引用对象,所以在其中任何地方修改后,其它地方也会发生改变 #endregion #region 知识点二 ScriptableObject的生命周期函数 //ScriptableObject和MonoBehavior很类似 //它也存在生命周期函数 //但是生命周期函数的数量更少 //主要做了解,一般我们使用较少 //Awake 数据文件创建时调用 //OnDestroy ScriptableObject 对象将被销毁时调用 //OnDisable ScriptableObject 对象销毁时、即将重新加载脚本程序集时 调用 //OnEnable ScriptableObject 创建或者加载对象时调用 //OnValidate 编辑器才会调用的函数,Unity在加载脚本或者Inspector窗口中更改值时调用 #endregion #region 知识点三 ScriptableObject好处的体现 //1.编辑器中的数据持久化 //通过代码修改数据对象中内容,会影响数据文件 //相当于达到了编辑器中数据持久化的目的 //(该数据持久化 只是在编辑模式下的持久,发布运行时并不会保存数据) data.i = 9999; data.f = 5.5f; data.b = false; //2.复用数据 //如果多个对象关联同一个数据文件 //相当于他们复用了一组数据,内存上更加节约空间 #endregion #region 总结 //其实创建出来的数据资源文件,你可以把它理解成一种记录数据的资源 //它的使用方式,和我们以前使用Unity当中的其它资源规则是一样的 //比如:预设体、音频文件、视频文件、动画控制器文件、材质球等等 //只不过通过继承ScriptableObject类生成的数据资源文件,它主要是和数据相关的 #endregion }
public MyData data; // Start is called before the first frame update void Start() { #region 知识点一 ScriptableObject的非持久化数据指的是什么 //指的是不管在编辑器模式还是在发布后都 不会持久化的数据 //我们可以根据自己的需求随时创建对应数据对象进行使用 //就好像直接new一个数据结构类对象 #endregion #region 知识点二 如何利用ScriptableObject生成非持久化的数据 //利用ScriptableObject中的静态方法 CreateInstance<>() //该方法可以在运行时创建出指定继承ScriptableObject的对象 //该对象只存在于内存当中,可以被GC //调用一次就创建一次 //通过这种方式创建出来的数据对象 它里面的默认值 不会受到脚本中设置的影响 //data = ScriptableObject.CreateInstance("MyData") as MyData; data = ScriptableObject.CreateInstance<MyData>(); data.PrintInfo(); #endregion #region 知识点三 ScriptableObject的非持久化数据存在的意义 //只是希望在运行时能有一组唯一的数据可以使用 //但是这个数据又不太希望保存为数据资源文件浪费硬盘空间 //那么ScriptableObject的非持久化数据就有了存在的意义 //它的特点是 //只在运行时使用,在编辑器模式下也不会保存在本地 #endregion }
原理就是将类保存到其他持久化方式中,类如json xml、playerprefs、2进制等等,其实无意义,
void Start() { #region 知识点一 回顾通过ScriptableObject创建非持久化数据 MyData data = ScriptableObject.CreateInstance<MyData>(); #endregion #region 知识点二 回顾数据持久化 //硬盘<=>内存 //使用数据时从硬盘中读取 //数据改变后保存到硬盘上 //游戏退出程序关闭后,数据信息会被存储到硬盘上,达到持久化的目的 //我们讲授过的数据持久化相关知识 //PlayerPrefs //XML //Json //2进制 //ScriptableObject并不适合用来做数据持久化功能 //但是我们可以利用我们学过的数据持久化方案 让其持久化 #endregion #region 知识点三 利用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); #endregion #region 知识点四 利用Json结合ScriptableObject读取数据 //从本地读取 Json字符串 string str = File.ReadAllText(Application.persistentDataPath + "/testJson.json"); //根据json字符串反序列化出数据 将内容覆盖到数据对象中 JsonUtility.FromJsonOverwrite(str, data); data.PrintInfo(); #endregion #region 总结 //对于ScriptableObject的数据 //由于它在游戏发布运行过程中无法被持久化 //我们可以利用 PlayerPrefs、XML、Json、2进制等等方式 //让其可以达到被真正持久化的目的 //但是我个人并不建议大家利用ScriptableObject来做数据持久化 //有点画蛇添足的意思了 #endregion }
例如 发射子弹,每个子弹上都有速度、攻击力等等(不变的,固定的),那么创建n个子弹就要开辟n份数据,这有点浪费。这样可以用通用的,然后只去改通用的,这些子弹就会都变化了。要是用单例去做,还要哪边都要去通过GetInstance去访问单例的对象,然后去写代码去更改,这里直接去更改数据更方便
public class Bullet : MonoBehaviour { public BulletInfo info; // Start is called before the first frame update void Start() { } // Update is called once per frame void Update() { this.transform.Translate(Vector3.forward * info.speed * Time.deltaTime); } } using System.Collections; using System.Collections.Generic; using UnityEngine; [CreateAssetMenu()] public class BulletInfo : ScriptableObject { public float speed; public int atk; } using System.Collections; using System.Collections.Generic; using UnityEngine; public class Lesson6 : MonoBehaviour { public BulletInfo info; // Start is called before the first frame update void Start() { #region 知识点一 使用预设体对象可能存在的内存浪费问题 //对于只用不变的数据 //以面向对象的思想去声明对象类是可能存在内存浪费的问题的 //我们以子弹对象为例 #endregion #region 知识点二 举例说明 利用ScriptableObject数据对象 更加节约内存 #endregion #region 总结 //对于不同对象,使用相同数据时 //我们可以使用ScriptableObject来节约内存 #endregion } // Update is called once per frame void Update() { if (Input.GetKeyDown(KeyCode.Space)) info.speed += 1; } }
用单例模式可以避免很多代码,例如,以前要手动拖取或者动态加载,浪费事,
//继承自这个类的子类,去创建子类的ScriptableObject 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; } } }
//这个TestData,去创建出一个名为TestData的asset,然后可以直接在其他类里点出来TestData.GetInstance().i
[CreateAssetMenu]
public class TestData : SingleScriptableObject<TestData>
{
public int i;
public bool b;
}
void Start() { #region 知识点一 为什么要单例模式化的获取数据 //对于只用不变并且要复用的数据 //比如配置文件中的数据 //我们往往需要在很多地方获取他们 //如果我们直接通过在脚本中 public关联 或者 动态加载 //如果在多处使用,会存在很多重复代码,效率较低 //如果我们将此类数据通过单例模式化的去获取 //可以提升效率,减少代码量 #endregion #region 知识点二 实现单例模式化获取数据 //知识点 //面向对象、单例模式、泛型等等 //我们可以实现一个ScriptableObject数据单例模式基类 //让我们只需要让子类继承该基类 //就可以直接获取到数据 //而不再需要去通过 public关联 和 资源动态加载 print(RoleInfo.Instance.roleList[0].id); print(RoleInfo.Instance.roleList[1].tips); print(TestData.Instance.i); print(TestData.Instance.b); #endregion #region 总结 //这种基类比较适合 配置数据 的管理和获取 //当我们的数据是 只用不变,并且是唯一的时候,可以使用该方式提高我们的开发效率 //在此基础上你也可以根据自己的需求进行变形 //比如添加数据持久化的功能,将数据从json中读取,并提供保存数据的方法 //但是不建议大家用ScriptableObject来制作数据持久化功能 //除非你有这方面的特殊需求 #endregion } // Update is called once per frame void Update() { }
参考:
https://blog.csdn.net/qq_46044366/article/details/124310241
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。