序列化,MonoBehaviour构造函数和Unity 5.4

从Unity5.4开始,为确保安全性和避免错误,新增了调用UnityAPI的限制,特别是在构造函数、字段初始化及反序列化过程中。大部分API只能在主线程调用,构造函数中调用特定API被视为不安全。这些改动旨在减少项目升级时的冲突,并将在未来版本中严格实施。

Starting with Unity 5.4, we have added new errors that are displayed when calling the Unity API from constructors/field initializers and during deserialization (loading). The purpose of these errors is to make the Unity API usage requirements clear and avoid any side effects incorrect usage might have.

从Unity 5.4开始,我们添加了从构造函数/字段初始化程序调用Unity API以及反序列化(加载)期间显示的新错误。 这些错误的目的是使Unity API使用要求明确,并避免不正确使用可能带来的任何副作用。

The majority of the Unity API should only be called from the main thread, e.g. from Start/Update/etc on MonoBehaviour. Similarly, only a subset of the Unity API should be called from script constructors/field initializers, like Debug.Log or Mathf. As Unity will invoke constructors when creating an instance of a class during deserialization (load), which might run on a non-main thread.
These requirements were not strictly enforced in versions of Unity prior to 5.4. Which could lead to crashes, race conditions and issues that were hard to diagnose and reproduce.

大多数Unity API只能从主线程中调用,例如,从MonoBehaviour上的Start / Update / etc中调用。 同样,应该从脚本构造函数/字段初始化程序(例如Debug.Log或Mathf)中调用Unity API的子集。 由于在反序列化(加载)期间创建类的实例时,Unity会调用构造函数,因此可能会在非主线程上运行。
这些要求未在5.4之前的Unity版本中严格执行。 这可能导致坠机,竞赛状况以及难以诊断和重现的问题。

In Unity 5.4, the new errors will in most cases not throw a managed exception and will not interrupt the execution flow of your scripts. This approach has been taken to reduce the amount of friction caused by upgrading your projects to Unity 5.4. These errors will throw a managed exception in a future release of Unity. We recommend that you fix these errors (if any) in your project when upgrading to 5.4.

在Unity 5.4中,新错误在大多数情况下不会引发托管异常,也不会中断脚本的执行流程。 已经采取了这种方法来减少因将项目升级到Unity 5.4而引起的摩擦。 这些错误 在将来的Unity版本中引发托管异常。 我们建议您在升级到5.4时在项目中修复这些错误(如果有)。

The new errors are documented in the “Script Serialization Errors” section on the Script Serialization page in the manual.
Let’s have a look at the new serialization errors in some common scenarios and how to fix them.

新错误记录在手册“脚本序列化” 上的“脚本序列化错误”部分 。
让我们看看一些常见情况下的新序列化错误以及如何修复它们。

从构造函数/字段初始化程序调用Unity API (Calling Unity API from constructor/field initializers)

When Unity creates an instance of your MonoBehaviour/ScriptableObject derived class, it calls the default constructor to create the managed object. When this happens, we are not yet in the main loop and the scene has not been fully loaded yet. Field initializers are also called when calling the default constructor of a managed object. Calling the Unity API from a constructor is considered unsafe for the majority of the Unity API.

当Unity创建MonoBehaviour / ScriptableObject派生类的实例时,它将调用默认构造函数来创建托管对象。 发生这种情况时,我们还没有进入主循环,场景还没有完全加载。 调用托管对象的默认构造函数时,也会调用字段初始化程序。 对于大多数Unity API而言,从构造函数调用Unity API被认为是不安全的。

Examples:

例子:

1

2
3
4
public class FieldAPICallBehaviour : MonoBehaviour
{
   public GameObject foo = GameObject.Find("foo");
}

1

2
3
4
public class FieldAPICallBehaviour : MonoBehaviour
{
   public GameObject foo = GameObject . Find ( "foo" ) ;
}
image01

1

2
3
4
5
6
7
8
9
10
public class ConstructorAPICallBehaviour : MonoBehaviour
{
   ConstructorAPICallBehaviour()
   {
       GameObject.Find("foo");
   }
}

1

2
3
4
5
6
7
8
9
10
public class ConstructorAPICallBehaviour : MonoBehaviour
{
   ConstructorAPICallBehaviour ( )
   {
       GameObject . Find ( "foo" ) ;
   }
}
image00

反序列化(加载)期间调用Unity API (Calling Unity API during deserialization (loading))

When Unity loads a scene, it recreates the managed objects from the saved scene and populates them with the saved values (deserializing). In order to create the managed objects, the default constructor for the objects must be called. If a field referencing an object is saved (serialized) and the object default constructor calls the Unity API you will get an error when loading the scene. As in the previous error, we are not yet in the main loop and the scene is not fully loaded. This is considered unsafe for the majority of the Unity API.

Unity加载场景时,它将根据保存的场景重新创建托管对象,并使用保存的值填充它们(反序列化)。 为了创建托管对象,必须调用对象的默认构造函数。 如果保存(序列化了)引用对象的字段,并且对象默认构造函数调用Unity API,则在加载场景时会出现错误。 与上一个错误一样,我们还没有进入主循环,场景还没有完全加载。 对于大多数Unity API而言,这被认为是不安全的。

Example:

例:

public class SerializationAPICallBehaviour : MonoBehaviour

公共 类 SerializationAPICallBehaviour : MonoBehaviour

1

2
3
4
5
6
7
8
9
10
11
12
{
   [System.Serializable]
   public class CallAPI
   {
       public CallAPI()
       {
           GameObject.Find("foo");
       }
   }
   CallAPI callAPI;
}

1

2
3
4
5
6
7
8
9
10
11
12
{
   [ System . Serializable ]
   public class CallAPI
   {
       public CallAPI ( )
       {
           GameObject . Find ( "foo" ) ;
       }
   }
   CallAPI callAPI ;
}
image02

反馈 (Feedback)

If you have any comments, questions or general feedback on these errors, you can post them here in this “Script Serialization Errors Feedback” thread on the Unity 5.4 beta forums.

如果您对这些错误有任何意见,疑问或一般反馈,可以 在Unity 5.4 beta论坛上的 “ 脚本序列化错误反馈 ”线程中将其 发布在此处 。

翻译自: https://blogs.unity3d.com/2016/06/06/serialization-monobehaviour-constructors-and-unity-5-4/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值