Unity使用ScriptableObject序列化资源

为什么要使用ScriptableObject序列化资源?

在设计模式中的抽象工厂模式或者建造者模式,其核心都是根据一份数据,创建出一个实体

数据的来源可以有很多种:

1.在脚本里初始化变量的时候赋予初始值

2.在脚本的初始值添加序列化字段,将创建出来的实体保存为预制体,在预制体的检查器页面设置实体数据的初始值

3.将数据保存在工厂类,在创建实体的时候为实体手动逐条赋值

4.在游戏开始时动态读取数据表赋予初始值

方法有很多,但是各自有各自的问题

在脚本中指定初始值,序列化变量,预制体设置序列化变量,工厂类逐条赋值,都有一个最根本的问题,每个单位的数值都绑定在单位自己的身上,当实体单位存在几百上千个的时候,会创建和个体相同数量的数据存储到计算机内存中,造成极大的内存浪费

比如游戏中的士兵,攻击力是10点,在你的游戏中有着一千个士兵,内存中就分配了1000个int或float类型变量的内存空间用来保存每个士兵的攻击力,但攻击力不同于当前生命值,是不会随着游戏进程而变化的,保存1000个相同的变量除了占据计算机内存使运行时电脑变的更卡以外一点作用都没有

将数据表的数据保存到数据类里面,再用实体访问数据类的数据,这样确实能够避免为多个相同的变量分配内存,但是数据表的数据类型毕竟是有限的,只能读取到字符串,在通过字符串转换成其他类似int,float之类的数据,遇到需要指定预制体,需要指定材质球,需要指定颜色的时候,就捉襟见肘了

在此,我隆重向大家介绍Unity专门为了解决这个问题而诞生的功能

ScriptableObject序列化资源


ScriptableObject序列化资源能做什么?

ScriptableObject序列化资源可以保存一份数据,这份数据被多个类同时访问同时只在加载时分配一次内存,避免了内存占用的问题

同时,在ScriptableObject序列化资源中可以指定几乎Unity中所有的资源类型,预制体,材质球,颜色,只要是在代码中可以用public关键字序列化出来的变量类型,都可以在编辑器中直接指定


ScriptableObject序列化资源要怎么用?

如何创建ScriptableObject序列化资源?

cs 复制代码
using UnityEngine;

[CreateAssetMenu(fileName = "PlayerData", menuName = "CreatScripTable/PlayerData")]
public class PlayerScripData : ScriptableObject
{
    public float hp = 100.0f;
    public int damage = 10;
    public string getName = "player";
    public Color color = Color.white;
    public GameObject prefab;
    public Material material;
}

上面这个脚本的功能就是创建ScriptableObject序列化资源

直接创建一个C#的Scrip脚本,然后将上面的内容粘贴并覆盖到脚本,就能创建ScriptableObject序列化资源了

CreateAssetMenu标签中需要指定两个变量的属性

fileName:创建出来文件的名字

menuName:通过选择右键菜单页面的哪个子选项创建资源

在脚本创建完成之后等待编辑器刷新一下,然后右键资源的空白部分,按照图片位置点击菜单选项,就可以创建出ScriptableObject序列化资源了,资源的名字可以随意更改

创建出来的资源如上图,其中资源的属性为继承了ScriptableObject类的数据类定义的带有public标签的变量,面板中的数值的初始值就是在脚本中指定的值,数据可以在编辑器中随意更改,预制体和材质也可以直接从资源页面拖拽,脚本中指定的值只影响创建资源的初始值,最终的数值以编辑器中输入的数值为准


如何使用ScriptableObject序列化资源?

核心只有一句代码

cs 复制代码
    public PlayerScripData playerData;

    void DebugValue()
    {
        Debug.Log("生命值:" + playerData.hp);
        Debug.Log("攻击力:" + playerData.damage);
    }

定义一个在编辑器中序列化出来的,继承了ScriptableObject类型的类的变量,然后在编辑器中将创建好的ScriptableObject序列化资源资源拖拽过去,然后直接通过变量访问里面的属性,访问出来的属性就是编辑器中指定的属性

下面是使用PlayerScripData写了个简单的工厂和实体的示例代码:

cs 复制代码
using UnityEngine;

public class CreatPlayerEntity : MonoBehaviour
{
    public PlayerScripData playerData;

    public void CreatPlayer()
    {
        GameObject g = GameObject.Instantiate(playerData.prefab);
        g.GetComponent<PlayerEntity>().Init(playerData);
    }
}
cs 复制代码
using UnityEngine;

public class PlayerEntity : MonoBehaviour
{
    private PlayerScripData playerData;
    private float hp;
    public void Init(PlayerScripData playerData)
    {
        this.playerData = playerData;
        hp = playerData.hp;
    }

    public void Hit(PlayerEntity player)
    {
        player.BeHit(playerData.damage);
    }

    public void BeHit(int damage)
    {
        hp -= damage;
    }
}
相关推荐
还是大剑师兰特1 天前
Unity3D(Unity)完整详细介绍
unity·游戏引擎
ellis19701 天前
u3d插件xLua[七]例6 Coroutine
unity
还是大剑师兰特1 天前
Unity 从零搭建简易3D场景(新手分步教程)
3d·unity·游戏引擎
神码编程1 天前
【Unity】TankBattle联机坦克大战(三)创建关卡(生成地块)
unity·游戏引擎·帧同步·坦克大战
淡海水1 天前
C#与常用数据结构源码剖析-全篇导览
开发语言·数据结构·unity·面试·职场和发展·c#
玖玥拾2 天前
Unity3D RPG 入门项目(四)背包拖拽、物品悬浮提示、项目开发思维
3d·unity·游戏引擎
xcLeigh2 天前
Unity基础:Start与Update方法——Unity脚本生命周期初探
java·unity·游戏引擎·教程
郝学胜-神的一滴2 天前
[简化版 GAMES 104] 现代游戏引擎 05:游戏引擎世界构建核心机制深度解析
c++·程序人生·unity·游戏引擎·计算机图形学·opengl
松树戈3 天前
godot项目【宝石捕手】04~添加音效、记分
游戏引擎·godot
LONGZETECH3 天前
无人机实训高成本痛点解法:虚拟仿真实现 70% 耗材损耗下降
大数据·算法·unity·架构·无人机