ScriptableObject 是一個資料容器(Data container),它透過共享通用資料的方式來減少對重複資料的記憶體佔用,進而降低你APP的記憶體使用量。
如果你的預製物件(Prefab)中儲存了一些不會改變的資料,那麼很適合把它們改為使用 ScriptableObject ,因為每當你實體化(instantiate)一個預製物件(Prefab)時,這個實體會保存自己的一份資料,當實體化很多個實體時,會有很多重複的資料佔用很多記憶體,因此你可以使用 ScriptableObject 可以把資料儲存起來,然後讓所有的預製物件(Prefab)存取這個 ScriptableObject 。
ScriptableObject 和 MonoBehaviour 一樣,繼承了 UnityEngine.Object ,但是與 MonoBehaviour 不同在於你不能把 ScriptableObject 附加(attach)到一個 GameObject 上,也不能進行 GatComponent 等對 GameObject 的操作,相反你需要把它儲存為資源(Asset)。
在使用Unity編輯器時,你可以把資料放在 ScriptableObject ,在執行時也可以調整其中的資料,但是你不可以把它當作遊戲存檔的工具。
使用 ScriptableObject 主要情況是在編輯時期修改 ScriptableObject 的資料,在執行時這些資料會被當作資源(Asset)使用。
使用方式 建立一個類並繼承 ScriptableObject,你可以使用 CreateAssetMenu 屬性(attribute),讓你方便在編輯器中使用,以下是一個範例:
1 2 3 4 5 6 7 8 [CreateAssetMenu(fileName = "Data" , menuName = "ScriptableObjects/SpawnManagerScriptableObject" , order = 1) ] public class SpawnManagerScriptableObject : ScriptableObject { public string prefabName; public int numberOfPrefabsToCreate; public Vector3[] spawnPoints; }
之後,你可以在 Assets -> Create -> ScriptableObjects -> SpawnManagerScriptableObject 中建立新的 ScriptableObject 實體。
你可以更改該實體的名稱與它的屬性。
接下來你可以在 MonoBehaviour 中使用這個 ScriptableObject 實體,如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 using UnityEngine;public class Spawner : MonoBehaviour { public GameObject entityToSpawn; 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[currentSpawnPointIndex], Quaternion.identity); currentEntity.name = spawnManagerValues.prefabName + instanceNumber; currentSpawnPointIndex = (currentSpawnPointIndex + 1 ) % spawnManagerValues.spawnPoints.Length; instanceNumber++; } } }
在Unity編輯器中,使用拖拉的方式將剛剛建立好的 ScriptableObject 實體拖拉到對應的位置上,另外 Box Prefab 是一個簡單的Square
最後在執行Unity,就可以看到Unity使用剛剛建立出來 ScriptableObject 資料去產生 Box 物件。
此外除了在編輯器中建立 實體,在執行期間也可以透過 CreateInstance 來建立。
1 ScriptableObject.CreateInstance<MyScriptableObjectClass>();
MonoBehaviour 與 ScriptableObject 的比較
MonoBehaviour
ScriptableObject
MonoBehaviour 接收所有來自 Unity 的 callback,像是 Start , Awake , Update , OnEnable ,OnDisabl , OnCollisonEnter 等
ScriptableObject 只接收一些: Awake , OnEnable , OnDestroy 與 OnDisable 。 在 Editor 中的話還有 OnValidate 與 Reset
MonoBehaviour 必須要 附加(attach)到 GameObject 上
ScriptableObject 不能附加到 GameObject 上,需要在專案(Project Level)中將它們儲存為 asset 檔案,在其他腳本中參考這些 ScriptableObject asset
當儲存 MonoBehaviour 時,會將它們的資料儲存到 Scenes 與 Prefabs 中
每個 ScriptableObject 實體都會被保存為專案層級(Project level)的獨立檔案中
一般在 Play Mode 中修改 MonoBehaviour 中的值之後離開 Play Mode 的話,這些值會被重新設定(Reset)
當離開 Play Mode 後, ScriptableObject 則不會重新設定。此外當編譯發布之後,執行期間 ScriptableObject 修改的值不會被保存,而是為發布時的值
在 ScriptableObject 中只有以下的 callback 會被呼叫
Awake : 與 MonoBehaviour 的類似,只有在 ScriptableObject 開始時會被呼叫。當遊戲執行(launched)或是有參考到這個 ScriptableObject asset 的 Scene 被載入時會呼叫。
OnEnable : 在 Awake 之後呼叫,當 ScriptableObject 被載入(Loaded)或是實體化(Instantiated)時會被呼叫。當 ScriptableObject.CreateInstance 或是 script 被重新編譯(recompilation)時 OnEnable 會被呼叫。
OnDisable : 當載入的 Scene 不再參考這個 ScriptableObject asset 時,就會呼叫 OnDisable , 它會在 OnDestory 之前被呼叫。此外在 script 重新編譯進入 Play Mode 時,也會呼叫,此時會出現 OnDisable 出現在 OnEnable 的情況。
OnDestory : 當 ScriptableObject 在 編輯器中刪除,或是重程式碼中刪除時,會呼叫 OnDestory 。如果是在執行期間建立的 ScriptableObject 在APP離開或是離開 Play Mode 時也會呼叫。
以下 callback 只在編輯器中呼叫
OnValidate : 當值在 Inspector 中改變值,才會呼叫。可以在這邊確保你的編輯器輸入的資料是合適的範圍(如 0 ~ 1)。
Reset : 當點擊 Inspector 中的 Reset 按鈕時,會呼叫。
返回 ScriptableObject 系列
Reference: