假設我有以下資料父類別
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using UnityEditor; | |
using System.Collections; | |
public abstract class DataSuperClass | |
{ | |
[SerializeField] | |
public string superStr = "super default str"; | |
public abstract void Draw(); | |
} |
以及子類別
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using UnityEditor; | |
using System.Collections; | |
[System.Serializable] | |
public class DataSubClass : DataSuperClass | |
{ | |
[SerializeField] | |
public string subStr = "sub default string"; | |
public override void Draw () | |
{ | |
subStr = EditorGUILayout.TextField("subStr", subStr); | |
} | |
} |
我在測試類別上宣告了一個父類別型態的List
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using System.Collections; | |
using System.Collections.Generic; | |
public class TestClass : MonoBehaviour | |
{ | |
[SerializeField] | |
public List<DataSuperClass> list = new List<DataSuperClass>(); | |
} |
同時我實做了TestClass的Inspector內容
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using UnityEditor; | |
using System.Collections; | |
[CustomEditor(typeof(TestClass))] | |
public class TestClassEditor : Editor | |
{ | |
public override void OnInspectorGUI () | |
{ | |
TestClass tc = (TestClass)target; | |
for(var i = 0; i < tc.list.Count; i++) | |
{ | |
tc.list[i].Draw(); | |
} | |
if(GUILayout.Button("Add")) | |
{ | |
tc.list.Add(new DataSubClass()); | |
} | |
} | |
} |
此時我將TestClass掛載到任意GameObject上
使用我自訂的Add鈕去新增數個DataSubClass到TestClass的List上
修改了裡頭的字串後, 將Unity存檔重開
重開後會赫然發現, DataSubClass的資料全不見了
這不是我所期盼的, 資料不應該遺失
該如何解決?
因此我想了很多關鍵字, 想辦法扒文
終於讓我找到修正這個錯誤的關鍵了
原文的解釋是這樣的
Unity determine the instance type via the variable type. If you store a subclass in a base class variable it gets serialized as base class.
However there is a way to use inheritance with serialization: ScriptableObject.
Your base class has to be derived from ScriptableObject. In this case Unity will remember the true type when you store a sub / child class in a base-class variable.
簡單翻譯就是:
Unity只認變數型別, 所以你如果把子類別實體存到父類別變數上去
那Unity在進行序列化儲存的時候, 就只會存父類別的內容
然而, Unity提供了一個很便利的解: ScriptableObject
只要你的父類別繼承了ScriptableObject
那麼他就能正確進行辨識了
下面附上修改後的父類別程式碼
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using UnityEditor; | |
using System.Collections; | |
public abstract class DataSuperClass : ScriptableObject | |
{ | |
[SerializeField] | |
public string superStr = "super default str"; | |
public abstract void Draw(); | |
} |
補充:
本來研究這個是為了要在StateMachineBehaviour搞花樣的
沒想到實際搬到StateMachineBehaviour後才發現
這個方法只能用在MonoBehaviour體系底下的
所以如果你想把這個方法用到StateMachineBehaviour
請及早收手吧, 歪路我走過了, 此路不通
沒有留言:
張貼留言