查看原文
其他

Unity 5.4中的序列化与MonoBehaviour构造函数

2016-06-07 Unity官方 Unity官方平台
出于调用Unity API的安全性考虑,我们在Unity 5.4中加入了一些新的错误类型。本文将由Unity产品团队,为大家介绍这些新的错误,以及将项目升级至Unity 5.4需要注意的地方。

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来说在构造函数中调用它们是不安全的。


示例:



上面这些示例代码会产生 “Find is not allowed to be called from a MonoBehaviour constructor (or instance field initializer), call in in Awake or Start instead. …”错误。修复的方法是将Unity API调用放到MonoBehaviour.Start方法中

在反序列化(加载时)过程中调用Unity API


当Unity加载场景时,它会从之前保存的场景中重建托管对象并且填入之前保存的值(反序列化)。为了创建托管对象,就必须调用对象的缺省构造函数。如果某个字段引用了之前被保存(序列化)的对象,并且对象的缺省构造函数中调用了Unity API,在加载场景时将会出现错误。就像之前提到的那个错误一样,我们还没有进入主循环并且场景还没有加载完成。这对于大多数Unity API来说都是不安全的。


示例:



这里出现了这样的错误“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官方中文论坛(forum.china.unity3d.com)发帖说明。


Unity官方活动


近期Unity官方将在上海举办官方教育培训活动,为参会者提供系统的Unity技能培训,梳理Unity相关的整个技能树以更好的应用到教学中。


如果您是院校老师(点击活动名称报名)

欢迎参与:Unity官方教育培训

活动时间:6月14日 - 6月16日

活动地点:上海


延展阅读

Unite Europe Keynote精彩回顾

文件I/O优化技巧

Unity图像特效教程|保留指定颜色

UnityEvent与C#事件系统性能对比

Unity中如何中断C#脚本的无限循环


我们还会分享更多Unity相关的技术内容在Unity官方中文论坛(forum.china.unity3d.com),请保持关注!



点击“阅读原文”进入Unity官方中文论坛!

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存