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
)或是有參考到這個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 按鈕時,會呼叫。
Reference: