我已将脚本附加到 Unity 游戏对象。该脚本包含各种公共(public)属性,包括我自己的一些类。就像在下面的简化代码中一样,其中 TestMonoBehaviorClass
附加到游戏对象,TestClass
' TestString
显示在检查器中。
public class TestMonoBehaviorClass : MonoBehaviour
{
public TestClass Test;
}
[System.Serializable]
public class TestClass
{
public string TestString;
public TestClass ()
{
Debug.Log ("TestClass creator called.");
this.TestString = "Reset String";
}
}
当我将脚本附加到游戏对象时,我希望 TestClass
的构造函数(编辑:不是从 MonoBehavior 派生的)被调用一次。但是如果我在 Unity 编辑器中运行程序然后停止程序,它会被调用四次。如果我将脚本附加到两个游戏对象,则可以执行七次。至少我多次在控制台中看到 Debug.Log 的输出。
不过,如果我在编辑器中更改 TestString
属性的内容,我手动输入的内容不会被覆盖!
为什么经常调用构造函数? 它在 Unity 的执行顺序 ( Unity's execution order of event functions ) 中何时被调用? 我可以忽略调用,还是必须在我的构造函数中添加特殊处理?到目前为止,我没有看到任何实际问题或副作用。
编辑: 好像只有没有参数的构造函数被调用了。如果我只有带参数的构造函数,则不会调用任何构造函数。
最佳答案
[System.Serializable]
是多次调用构造函数的原因。忽略它,除非因此导致错误,然后询问有关该特定错误的问题以获得变通解决方案。如果您删除 [System.Serializable]
,Unity 将不会序列化 TestClass
类,构造函数将被调用一次,而不是多次。
Edit: It seems that only constructors without parameters are called. If I only have constructors with parameters, then none is called.
使用[System.Serializable]
,Unity序列化会在序列化和淡化过程中多次调用默认构造函数,因为反序列化时需要重新创建Object。构造函数用于执行此操作。参见 this在 Unity 中发布其他类似的多构造函数调用问题。
<支持> 编辑:
如果你想在序列化完成之前或之后做一些事情,你可以实现 ISerializationCallbackReceiver
界面并使用OnBeforeSerialize()
或 OnAfterDeserialize()
函数分别执行此操作。
例如:
[System.Serializable]
public class TestClass : ISerializationCallbackReceiver
{
public string TestString;
public TestClass()
{
Thread thread = Thread.CurrentThread;
Debug.Log("TestClass creator called: " + thread.ManagedThreadId);
this.TestString = "Reset String";
}
public void OnAfterDeserialize()
{
Thread thread = Thread.CurrentThread;
Debug.LogWarning("OnAfterDeserialize Thread ID: " + thread.ManagedThreadId);
}
public void OnBeforeSerialize()
{
Thread thread = Thread.CurrentThread;
Debug.LogWarning("OnBeforeSerialize Thread ID: " + thread.ManagedThreadId);
}
}
关于c# - 为什么在非 MonoBehaviour 序列化类中调用多个构造函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46424378/