我已将脚本附加到Unity游戏对象。该脚本包含各种公共属性,包括我自己的一些类。与以下简化代码类似,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)中调用? 我可以忽略调用,还是必须在构造函数中添加特殊处理?到目前为止,我没有看到任何实际问题或副作用。
编辑: 似乎只调用没有参数的构造函数。如果我只有带参数的构造函数,则不会调用任何构造函数。
答案 0 :(得分:6)
[System.Serializable]
是多次调用构造函数的原因。只要忽略它,除非因此而导致错误,然后询问有关解决方案的特定错误的问题。如果您删除[System.Serializable]
,Unity将不会序列化TestClass
类,构造函数将被称为一次而不是多次。
编辑:似乎只调用没有参数的构造函数。 如果我只有带参数的构造函数,则不调用任何构造函数。
使用[System.Serializable]
,Unity序列化将在序列化和脱盐期间多次调用默认构造函数,因为它需要在反序列化时重新创建对象。构造函数用于执行此操作。有关Unity中其他类似的多个构造函数调用问题,请参阅this帖子。
修改强> 功能
如果要在序列化完成之前或之后执行操作,可以实现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);
}
}
答案 1 :(得分:0)
您不应该在Unity中使用构造函数而是使用Awake函数来分配值,否则您可以创建自己的setter函数来设置值。
请检查:http://answers.unity3d.com/questions/862032/c-constructor-in-monobehaviour.html