Version: 6000.3
语言: 中文
在运行时向对象添加功能
酒店访客

财产袋

属性包是给定 .Net 对象类型的属性集合,可用于访问和设置该类型对象实例的数据。

概念

给定类型的属性包是一个配套对象,它支持基于该类型的实例的高效数据遍历算法。默认情况下,Unity 使用反射为类型生成属性包。这种反射性方法提供了便利,并且当财产袋尚未注册时,每种类型仅延迟发生一次。

为了提高性能,您可以通过使用[Unity.Properties.GeneratePropertyBag].此外,要激活代码生成,您必须使用[assembly: Unity.Properties.GeneratePropertyBagsForAssembly].代码生成的属性包在加载域时自动注册。

在反射和代码生成方案中,属性包都会生成以下属性:

属性包不会为标记为[DontCreateProperty].

如果字段是只读的,或者该属性只有一个 getter,则生成的属性是只读的。

您还可以使用[Unity.Properties.CreateProperty(ReadOnly = true)]使生成的属性为只读。

为了方便起见,使用序列化属性在属性包中创建属性并不总是首选方法。Unity 的序列化系统只能对字段和自动属性进行作,这使得有效地实现验证或传播更改变得具有挑战性。

以下示例将 Unity 序列化系统与 Unity 属性系统相结合:

using UnityEngine;
using Unity.Properties;

public class MyBehaviour : MonoBehaviour
{
    // Serializations go through the field, but we don't want to create a property for it.
    [SerializeField, DontCreateProperty] 
    private int m_Value;
    
    // For the property bag, use the property instead of the field. This ensures that
    // the value stays within the appropriate bounds.
    [CreateProperty] 
    public int value
    {
        get => m_Value;
        set => m_Value = value;
    }
    
    // This is a similar example, but for an auto-property.
    [field: SerializeField, DontCreateProperty]
    [CreateProperty]
    public float floatValue { get; set; }
}

与 Unity 序列化系统不同,属性包中的属性不符合[SerializeField].相反,结构类型被识别为值类型,而类类型被识别为引用。

在 Unity 序列化中,虽然支持多态性,但必须使用[SerializeReference]属性以显式选择加入。否则,实例将序列化为值类型。值得注意的是UnityEngine.Object类型是此规则的例外,因为它们会自动序列化为引用类型。

性能注意事项

Unity 属性使用 .Net 反射来创建属性包和强类型的属性,这可能会在您首次为给定容器类型请求属性包时引入性能开销。

通过反射为字段成员创建属性时,这些属性可能会在IL2CPP Unity 开发的脚本后端,在为某些平台构建项目时,可以将其用作 Mono 的替代方案。更多信息
请参阅术语表
建立。这种分配是由于直接使用System.Reflection.FieldInfo,这导致了不可避免的拳击。

为避免反射,可以在编译期间代码生成属性包。但是,请注意,这种优化可能会导致编译时间更长。若要为程序集启用代码生成,请使用[Unity.Properties.GeneratePropertyBagsForAssemblyAttribute]并使用[Unity.Properties.GeneratePropertyBagAttribute].若要使属性包能够访问内部和专用字段和属性,请将类型设置为partial.

其他资源

在运行时向对象添加功能
酒店访客