# ScriptableObject

> Inherit from ScriptableObject to store data that's independent of GameObjects.

ScriptableObject 是一个可独立于类实例来保存大量数据的数据容器。ScriptableObject 的一个主要用途是通过避免重复值来减少项目的内存使用量。如果项目有一个预制件在附加的 MonoBehaviour 脚本中存储不变的数据，这将非常有用。

每次实例化预制件时，都会产生单独的数据副本。这种情况下可以不使用该方法并且不存储重复数据，而是使用 ScriptableObject 来存储数据，然后通过所有预制件的引用访问数据。这意味着内存中只有一个数据副本。

就像 MonoBehaviour 一样，ScriptableObject 派生自基本 `UnityEngine.Object`，但不同于 MonoBehaviour 之处在于，不能将 ScriptableObject 附加到[游戏对象](/engine/6000.0/manual/scripting/get-started/fundamental-unity-types/class-game-object.md)。正确的做法是需要将它们保存为项目中的资源。

如果使用 Unity Editor，可以在编辑时和运行时将数据保存到 ScriptableObjects，因为 ScriptableObjects 使用 Editor 命名空间和 Editor 脚本。但是，在已部署的构建中，不能使用 ScriptableObject 来保存数据，但可以使用在开发期间设置的 ScriptableObject 资源中保存的数据。

将来自 Editor 的数据在作为资源保存到 ScriptableObject 时，Unity 将数据写入磁盘，且其会在会话之间一直保留。

此页面概述了 ScriptableObject 类及其在脚本编写中的常见用法。有关 ScriptableObject 类的每个成员的详尽参考，请参阅 [ScriptableObject 脚本参考](/engine/6000.0/script-reference/unity-engine/scriptable-object.md)。

## 使用 ScriptableObject

ScriptableObjects 的主要用例为：

* 在 Editor 会话期间保存和存储数据
* 将数据保存为项目中的资源，以便在运行时使用

ScriptableObject 必须继承自 [ScriptableObject](/engine/6000.0/script-reference/unity-engine/scriptable-object.md) 类。

要创建新的 ScriptableObject 脚本，请执行以下操作之一：

* 在主菜单中，转到**资源 (Assets)** > **创建 (Create)** > **脚本 (Scripting)** >，然后选择 **ScriptableObject Script**。
* 在 [Project 窗口工具栏](/engine/6000.0/manual/unity-editor/using-the-editor/project-view.md)中，右键单击以打开 Project 窗口上下文菜单，然后选择**创建 (Create)** > **脚本 (Scripting)** > **ScriptableObject 脚本(ScriptableObject Script)**。还可以单击 Project 窗口中的加号来直接打开**创建 (Create)** 菜单。

可以使用 [CreateAssetMenu](/engine/6000.0/script-reference/unity-engine/create-asset-menu-attribute.md) 属性创建自定义资源（使用类）。例如：

```
using UnityEngine;

[CreateAssetMenu(fileName = "Data", menuName = "ScriptableObjects/SpawnManagerScriptableObject", order = 1)]
public class SpawnManagerScriptableObject : ScriptableObject
{
    public string prefabName;

    public int numberOfPrefabsToCreate;
    public Vector3[] spawnPoints;
}
```

使用上述在 **Assets** 文件夹中创建的脚本，您可以通过导航到\_\_资源 (Assets) > 创建 (Create) > ScriptableObjects > SpawnManagerScriptableObject\_\_ 来创建 ScriptableObject 的实例。为新的 ScriptableObject 实例提供有意义的名称并更改值。要使用这些值，必须创建一个引用 ScriptableObject（在本例中为 `SpawnManagerScriptableObject`）的新脚本。例如：

```
using UnityEngine;

public class Spawner : MonoBehaviour
{
    // The GameObject to instantiate.
    public GameObject entityToSpawn;

    // An instance of the ScriptableObject defined above.
    public SpawnManagerScriptableObject spawnManagerValues;

    // This will be appended to the name of the created entities and increment when each is created.
    int instanceNumber = 1;

    void Start()
    {
        SpawnEntities();
    }

    void SpawnEntities()
    {
        int currentSpawnPointIndex = 0;

        for (int i = 0; i < spawnManagerValues.numberOfPrefabsToCreate; i++)
        {
            // Creates an instance of the prefab at the current spawn point.
            GameObject currentEntity = Instantiate(entityToSpawn, spawnManagerValues.spawnPoints[currentSpawnPointIndex], Quaternion.identity);

            // Sets the name of the instantiated entity to be the string defined in the ScriptableObject and then appends it with a unique number. 
            currentEntity.name = spawnManagerValues.prefabName + instanceNumber;

            // Moves to the next spawn point index. If it goes out of range, it wraps back to the start.
            currentSpawnPointIndex = (currentSpawnPointIndex + 1) % spawnManagerValues.spawnPoints.Length;

            instanceNumber++;
        }
    }
}
```

> \*\*注意：\*\*脚本文件与类的名称必须相同。

将先前的脚本附加到[场景](/engine/6000.0/manual/working-in-unity/working-with-scenes/creating-scenes.md)中的游戏对象。然后，在 Inspector 中，将 **Spawn Manager Values** 字段设置为新设置的 `SpawnManagerScriptableObject`。

将 **Entity To Spawn** 字段设置为 Assets 文件夹中的任何预制件，然后在 Editor 中单击 **Play**。在 `Spawner` 中引用的预制件会使用在 `SpawnManagerScriptableObject` 实例中设置的值来实例化。

如果在 Inspector 中使用 ScriptableObject 引用，可以双击引用字段来打开 ScriptableObject 的 Inspector。还可以创建自定义编辑器来定义该类型的 Inspector 外观，从而帮助管理它所代表的数据。

## 其他资源

* [ScriptableObject API 参考](/engine/6000.0/script-reference/unity-engine/scriptable-object.md)
* [ScriptableObject 简介](https://learn.unity.com/tutorial/introduction-to-scriptable-objects)
