为什么在非MonoBehaviour序列化类中进行多个构造函数调用?

时间:2017-09-26 10:47:13

标签: c# unity3d constructor execution inspector

我已将脚本附加到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)中调用? 我可以忽略调用,还是必须在构造函数中添加特殊处理?到目前为止,我没有看到任何实际问题或副作用。

编辑: 似乎只调用没有参数的构造函数。如果我只有带参数的构造函数,则不会调用任何构造函数。

2 个答案:

答案 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