ScriptableObject 基礎
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 | [] |
之後,你可以在 Assets -> Create -> ScriptableObjects -> SpawnManagerScriptableObject 中建立新的 ScriptableObject 實體。
你可以更改該實體的名稱與它的屬性。
接下來你可以在 MonoBehaviour 中使用這個 ScriptableObject 實體,如下
1 | using UnityEngine; |
在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)或是有參考到這個ScriptableObjectasset 的Scene被載入時會呼叫。OnEnable: 在Awake之後呼叫,當ScriptableObject被載入(Loaded)或是實體化(Instantiated)時會被呼叫。當ScriptableObject.CreateInstance或是 script 被重新編譯(recompilation)時OnEnable會被呼叫。OnDisable: 當載入的Scene不再參考這個ScriptableObjectasset 時,就會呼叫OnDisable, 它會在OnDestory之前被呼叫。此外在 script 重新編譯進入Play Mode時,也會呼叫,此時會出現OnDisable出現在OnEnable的情況。OnDestory: 當ScriptableObject在 編輯器中刪除,或是重程式碼中刪除時,會呼叫OnDestory。如果是在執行期間建立的ScriptableObject在APP離開或是離開Play Mode時也會呼叫。
以下 callback 只在編輯器中呼叫
OnValidate: 當值在Inspector中改變值,才會呼叫。可以在這邊確保你的編輯器輸入的資料是合適的範圍(如 0 ~ 1)。Reset: 當點擊Inspector中的 Reset 按鈕時,會呼叫。
Reference: