franciscochonge 发表于 2022-7-6 09:43

Unity3D ScriptableObject的使用

前言

通过本文的学习你可以快速了解SctiptableObject,本文看完只需要10分钟让你腾飞。
为了可以让大家更快了解什么是ScriptableObject,我使用两种方式,第一转述官网说明,第二使用官网用例展示。
对ScriptObject不是什么神奇的东西,只是Unity使用了高效的存储方式保存数据,有机会我们可以对Unity3d的源码进行剖析(有了源码心就放宽了)
一、官网手册说明

这次我选择了中文官网
https://docs.unity.cn/cn/current/Manual/class-ScriptableObject.html


1、ScriptableObject

ScriptableObject 是一个可独立于类实例来保存大量数据的数据容器。ScriptableObject 的一个主要用例是通过避免重复值来减少项目的内存使用量。如果项目有一个预制件在附加的 MonoBehaviour 脚本中存储不变的数据,这将非常有用。
每次实例化预制件时,都会产生单独的数据副本。这种情况下可以不使用该方法并且不存储重复数据,而是使用 ScriptableObject 来存储数据,然后通过所有预制件的引用访问数据。这意味着内存中只有一个数据副本。
就像 MonoBehaviour 一样,ScriptableObject 派生自基本 Unity 对象,但与 MonoBehaviour 不同,不能将 ScriptableObject 附加到游戏对象。正确的做法是需要将它们保存为项目中的资源。
如果使用 Editor,可以在编辑时和运行时将数据保存到 ScriptableObject,因为 ScriptableObject 使用 Editor 命名空间和 Editor 脚本。但是,在已部署的构建中,不能使用 ScriptableObject 来保存数据,但可以使用在开发期间设置的 ScriptableObject 资源中保存的数据。
从 Editor 工具作为资源保存到 ScriptableObject 的数据将写入磁盘,因此将在会话之间一直保留。
此页面概述 ScriptableObject 类及其在脚本编写中的常见用法。有关 ScriptableObject 类的每个成员的详尽参考,请参阅 ScriptableObject 脚本参考。
2、使用 ScriptableObject

ScriptableObjects 的主要用例为:

[*]在 Editor 会话期间保存和存储数据
[*]将数据保存为项目中的资源,以便在运行时使用
=====以上是官网说明
3、总结

ScriptableObject是一个高效的配置读取方案,有了他可以制作可视化数据配置。
二、测试ScriptableObject

1、通过Menu创建可配置的ScriptObject

using System.Collections;
using UnityEngine;


public class SpawnManagerScriptableObject : ScriptableObject
{
    public string prefabName;

    public int numberOfPrefabsToCreate;
    public Vector3[] spawnPoints;
}
2、创建一个ScriptObject对象



3、开始我们的配置工作



4、写一个测试脚本

using UnityEngine;

public class Spawner : MonoBehaviour
{
    // 要实例化的游戏对象。
    public GameObject entityToSpawn;

    //上面定义的 ScriptableObject 的一个实例。
    public SpawnManagerScriptableObject spawnManagerValues;

    //这将附加到创建的实体的名称,并在创建每个实体时递增。
    int instanceNumber = 1;

    void Start()
    {
      SpawnEntities();
    }

    void SpawnEntities()
    {
      int currentSpawnPointIndex = 0;

      for (int i = 0; i < spawnManagerValues.numberOfPrefabsToCreate; i++)
      {
            //在当前生成点处创建预制件的实例。
            GameObject currentEntity = Instantiate(entityToSpawn, spawnManagerValues.spawnPoints, Quaternion.identity);

            //将实例化实体的名称设置为 ScriptableObject 中定义的字符串,然后为其附加一个唯一编号。
            currentEntity.name = spawnManagerValues.prefabName + instanceNumber;

            // 移动到下一个生成点索引。如果超出范围,则回到起始点。
            currentSpawnPointIndex = (currentSpawnPointIndex + 1) % spawnManagerValues.spawnPoints.Length;

            instanceNumber++;
      }
    }
}5、创建 TestScriptableObject对象

把SpwawnManagerSciprt挂上去
创建一个Cube的prefab放挂上去,把运行的SpawnManagerValues的配置文件附加上


6、运行效果



三、 ScriptableObject相应的文档

1、ScriptableObject API 文档

让我们看看Script API 中对Scriptable的一些描述
https://docs.unity.cn/cn/current/ScriptReference/ScriptableObject.html


2、CreateInstance

在API文档中我最想尝试的接口是


函数说明


   在SpawneEnities中加入
void CreateBySelf()
{
    spawnManagerValues = ScriptableObject.CreateInstance<SpawnManagerScriptableObject>();
    if (spawnManagerValues != null)
    {
      spawnManagerValues.numberOfPrefabsToCreate = 3;
      spawnManagerValues.prefabName = "AICreateSO";
      //随机位置
      Vector3 pos1 = Random.insideUnitSphere;
      Vector3 pos2 = Random.insideUnitSphere;
      Vector3 pos3 = Random.insideUnitSphere;
      spawnManagerValues.spawnPoints = new Vector3;
      spawnManagerValues.spawnPoints = pos1;
      spawnManagerValues.spawnPoints = pos2;
      spawnManagerValues.spawnPoints = pos3;
    }
}
修改SpawnEntities()中加入以下
if (spawnManagerValues == null)
{
   this.CreateBySelf();
}当SpawManagerValues为空时



spawn Mabager Values设置为空


总结

      继承自己ScriptableObject的脚本其实就是一个配置文件的读取和生成器,通过ScriptableObject的Asset对象可以配置用户想要的数据。
页: [1]
查看完整版本: Unity3D ScriptableObject的使用