说明:在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