ScriptableObject

本篇文章出處自 https://docs.unity3d.com/2022.3/Documentation/Manual/class-ScriptableObject.html
軟體版本與本翻譯文件可能會有落差,本翻譯文件僅供參考。

切換到 Scripting(腳本)

ScriptableObject 是一種資料容器,你可以用它在不依賴類別實例的情況下,保存大量資料。ScriptableObject 的主要用途之一,是透過避免重複複製數值來降低專案的記憶體用量。這在你的專案中有一個 Prefab,並且把「不會改變的資料」儲存在所掛載的 MonoBehaviour 腳本裡時特別有用。

每次你實例化(instantiate)那個 Prefab 時,它都會得到那份資料的一份拷貝。你可以不要用這種方式(也就是儲存重複資料),改用 ScriptableObject 來保存資料,然後讓所有 Prefab 都用參考(reference)的方式去存取它。這樣記憶體裡就只會有一份資料拷貝。

和 MonoBehaviour 一樣,ScriptableObject 也是從 Unity 的基礎物件(base Unity object)衍生而來;但與 MonoBehaviour 不同的是,你不能把 ScriptableObject 掛到 GameObject 上。相反地,你需要把它存成你專案中的 Asset(資產)。

在使用 Editor(編輯器)時,你可以在編輯期間以及執行期間把資料存到 ScriptableObject,因為 ScriptableObject 會使用 Editor 命名空間與 Editor 腳本功能。不過在部署後的 Build(發佈版本)中,你不能用 ScriptableObject 來保存資料;但你仍然可以使用你在開發期間建立好的 ScriptableObject 資產中所保存的資料。

你透過 Editor 工具把資料存成 ScriptableObject 資產時,資料會被寫入磁碟,因此能在不同工作階段之間持久保存。

本頁提供 ScriptableObject 類別的概覽,以及在撰寫腳本時的常見用途。若要查看 ScriptableObject 類別每個成員的完整參考,請見 ScriptableObject 的 Script Reference(腳本參考文件)。

使用 ScriptableObject

ScriptableObject 的主要使用情境是:

  • 在 Editor 工作階段中儲存與保存資料
  • 將資料以資產(Asset)的形式儲存在你的專案中,供執行時(runtime)使用

要使用 ScriptableObject,請在你的應用程式 Assets 資料夾中建立一個腳本,並讓它繼承自 ScriptableObject 類別。你可以使用 CreateAssetMenu 屬性(attribute),讓你更容易用這個類別建立自訂資產。舉例來說:


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 實例取一個有意義的名稱,並修改其中的數值。

要使用這些數值,你需要再建立一個新的腳本,用來參考(reference)你的 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++;
        }
    }
}

注意:腳本檔案的名稱必須和類別名稱相同。

把上面的腳本掛到你場景(Scene)中的某個 GameObject 上。接著在 Inspector 裡,將 Spawn Manager Values 欄位指定為你剛建立並設定好的 SpawnManagerScriptableObject。

把 Entity To Spawn 欄位設為你 Assets 資料夾中的任意 Prefab,然後在 Editor 中按下 Play。你在 Spawner 裡所參考的那個 Prefab,就會依照你在 SpawnManagerScriptableObject 實例中設定的數值被實例化(instantiate)。

如果你是在 Inspector 裡操作 ScriptableObject 的參考欄位,你可以在那個參考欄位上雙擊,直接打開該 ScriptableObject 的 Inspector。你也可以建立自訂的 Editor,用來定義你的類型在 Inspector 中的外觀,協助你管理它所代表的資料。

留言

這個網誌中的熱門文章