从Unity 5.4开始,我们加入了新的错误类型,在反序列化(加载时)中从构造函数或字段初始化方法中调用Unity API时会显示这些错误。引入这些错误是为了让使用Unity API的要求更加清晰并且避免任何使用不当可能产生的不良影响。
大多数Unity API都应只在主线程中调用,例如MonoBehaviour的Start/Update等方法。同样,只有Unity API的子集可以在脚本的构造函数或字段初始化方法中调用,例如Debug.Log 或Mathf。因为在反序列化(加载)过程中Unity会在创建类实例的时候调用构造函数,这个调用可能不会跑在主线程上。

这些要求在Unity 5.4之前的版本没有严格的限制。这就可能会导致程序崩溃,竟态条件或者很难诊断或者重现的问题。

在Unity 5.4中,这些新的错误在大多数情况下都不会抛出托管异常也不会终止脚本的执行。这么做的目的是减少将项目升级到Unity 5.4所产生的冲突。这些错误在Unity将来的发行版本中会抛出托管异常。我们建议在升级项目到5.4的时候就修复这些错误(如果存在)。

可以在手册的Script Serialization页的“Script Serialization Errors” 部分找到关于这些错误的文档说明。

让我们看看这些新的序列化错误的常见情形以及如何修复它们。

在构造函数或字段初始化方法中调用Unity API
当Unity创建从MonoBehaviour/ScriptableObject继承来的对象实例时,它会调用缺省构造函数来创建这个托管对象。到这一步时,我们还没有执行到主循环并且场景也还没有加载完成。字段初始化方法也是在调用托管对象的缺省构造函数时被调用的。对于多数Unity API来说在构造函数中调用它们是不安全的。

示例:
[C#] 纯文本查看 复制代码public class FieldAPICallBehaviour : MonoBehaviour { public GameObject foo = GameObject.Find(foo); }
102904ekvtzl2l1akoht9y.png
[C#] 纯文本查看 复制代码ublic class SerializationAPICallBehaviour : MonoBehaviour { [System.Serializable] public class CallAPI { public CallAPI() { GameObject.Find(foo); } } CallAPI callAPI; }
102905wpdlnlwe5wv5h87p.png
在反序列化(加载时)过程中调用Unity API
当Unity加载场景时,它会从之前保存的场景中重建托管对象并且填入之前保存的值(反序列化)。为了创建托管对象,就必须调用对象的缺省构造函数。如果某个字段引用了之前被保存(序列化)的对象,并且对象的缺省构造函数中调用了Unity API,在加载场景时将会出现错误。就像之前提到的那个错误一样,我们还没有进入主循环并且场景还没有加载完成。这对于大多数Unity API来说都是不安全的。

示例:
[C#] 纯文本查看 复制代码public class SerializationAPICallBehaviour : MonoBehaviour { [System.Serializable] public class CallAPI { public CallAPI() { GameObject.Find(foo); } } CallAPI callAPI;
102905n26bbz2sm7hmdivv.png
这里出现了这样的错误“Find is not allowed to be called during serialization, call it from Awake or Start instead.”修复这个问题需要重构代码来保证在任何序列化对象的所有构造函数中都没有调用Unity API。如果某些对象一定要调用Unity API,必须在某个主线程中的MonoBehaviour 的回调函数中调用,例如Start, Awake 或者Update。

反馈
如果对这些错误有任何建议,问题或者反馈,请访问Unity 5.4 beta论坛的“Script Serialization Errors Feedback”中进行回复。
Unity, 序列化锐亚教育

锐亚教育 锐亚科技 unity unity教程