說明:在unity3d中自己定義的scriptobject中使用了一個可以序列化的類,希望可以在界面上顯示,但這個類的一個樹型結構,其中包含了同類型的列表。這種情況下,利用unity自己的序列化方式雖然能夠用,但官方強烈不讓這樣用,還直接報紅:Serialization depth limit exceeded at '‘. There may be an object composition cycle in one or more of your serialized classes.,爲些想了不少辦法,但最終還是需要利用unity自身的序列化方式,不然後不能在界面上顯示,也就沒有達到可視化的效果。
一、問題來源
1.源碼
using System.Collections.Generic;
[System.Serializable]
public class Person {
public string name;
public List<Person> childs;
}
[CreateAssetMenu(menuName = "創建FamilyObj")]
public class FamilyObj : ScriptableObject {
public Person personRoot;
2.問題說明
以上分別是對象模型和一個ScriptObject的腳本,此時,一創建出一個FamilyObj,編輯器就會報紅。主要是因爲這種序列化的方案不運行空的列表,一但開始序列化,理論會無限創建對象。而unity對這種方案支持的效果不會超過7級,如下圖所示:
二、解決方案
1.方案來源
由於這個問題網上十分普遍,但是並沒有找到能夠滿足需求的方案,大多是告訴你怎麼不讓報錯。但並沒有說怎麼還能顯示在界面上的同時不報錯,
這是官方說明怎麼序列化非常規的類型如字典:https://docs.unity3d.com/ScriptReference/ISerializationCallbackReceiver.html
這是官方說明怎麼自己定義序列化:https://docs.unity3d.com/Manual/script-Serialization.html
以上的兩個貌似對我也沒有什麼啓發,也沒有實現要在界面上顯示多層級的樹型結構。
2.利用繼承和自定義層級的方案
這裏說一個我程序內的解決方案:
using System.Collections.Generic;
public abstract class Person {
public string name;
public abstract List<Person> childs { get; set; }
[System.Serializable]
public class P1 : Person
{
public List<P2> _childs;
public override List<Person> childs
{
get
{
return _childs.ConvertAll<Person>(x=>x);
}
set
{
_childs = value.ConvertAll(x => x as P2);
}
}
}
[System.Serializable]
public class P2 : Person
{
public List<P3> _childs;
public override List<Person> childs
{
get
{
return _childs.ConvertAll<Person>(x => x);
}
set
{
_childs = value.ConvertAll(x => x as P3);
}
}
}
[System.Serializable]
public class P3 : Person
{
public override List<Person> childs
{
get
{
Debug.Log("不孕不育");
return null;
}
set
{
Debug.Log("不孕不育");
}
}
}
}
[CreateAssetMenu(menuName = "創建FamilyObj")]
public class FamilyObj : ScriptableObject {
public Person.P1 personRoot;
}
以上爲修改後的類,因爲並沒有引用自己同類型的對象,而且最後一級也已經指定了空,所以程序也並不會報錯。由於其他子類都繼承於一個抽象類,其他業務邏輯並不會發生改變,主要是創建的時候,需要指定是具體的那個類。此時最好寫個對象創建的功能,但並不在本文的討論範圍內。
三、相關文章
雖然,目前已經不會報錯了,但由於程序的擴展性問題,這種方案其實還是個問題。一般情況下子層級是有限的,好辦到是好辦,多加一級就要寫不少重複的代碼。希望可以遇到更好的解決方案。
下面是一些相關的網站:
Custom serialization:docs.unity3d.com/Manual/script-Serialization-Custom.html
Script serialization errors:https://docs.unity3d.com/Manual/script-Serialization-Errors.html