为解决Inspector面板序列化抽象类过于冗杂提供了一些方案
通常情况下,我们会使用Unity的[SerializeReference]
特性来在Inspector
面板对抽象字段进行序列化操作,缺点可能就是需要为脚本提供一些Editor函数来为抽象字段决定真正的类型
public interface IPerson { }
[Serializable]
public class Teacher : IPerson
{
[SerializeField] int m_teachID;
}
[Serializable]
public class Student : IPerson
{
[SerializeField] string m_name;
}
public class Test : MonoBehaviour
{
[SerializeReference] IPerson peopel;
[ContextMenu("Add Student")]
private void AddStudent() {
peopel = new Student();
}
[ContextMenu("Add Teacher")]
public void AddTeacher() {
peopel = new Teacher();
}
}
使用[SerializeExtension]
特性可以在Inspector
面板添加选择框来去除给脚本添加的Editor代码
public class Test : MonoBehaviour
{
[SerializeExtension]
[SerializeReference] IPerson peopel;
}
有时候我们需要对Inspector
面板传入的值做一些校验或者是特殊的处理,可以在使用[SerializeExtension]
特性时选择传入proxyPropertyName
参数来实现对字段赋值时调用特定属性来代理赋值。proxyPropertyName
为属性名称的字符串
public class Test : MonoBehaviour
{
[SerializeExtension(proxyPropertyName: nameof(Health))]
[SerializeField] int m_health;
public int Health {
get => m_health;
set => m_health = mathf.clamp(value, 0, 100);
}
}
在使用[SerializeExtension]
特性时选择传入canWrite
参数来实现字段在Inspector
面板上是否可以修改
[Serializable]
public class Student : IPerson
{
[SerializeExtension(canWrite: false)]
[SerializeField] string m_name = "ABC";
}
public class Test : MonoBehaviour
{
[SerializeExtension]
[SerializeReference] IPerson peopel;
[SerializeField] int a = 10;
[SerializeExtension(canWrite: false)]
[SerializeField] int b = 20;
}