プロパティバッグは、.Net の特定のオブジェクト型のプロパティをコレクションしたものです。プロパティバッグを使用して、その型のオブジェクトのインスタンスデータにアクセスし、設定することができます。
特定の型のプロパティバッグはコンパニオンオブジェクトとして機能し、その型のインスタンスに基づいて効率的なデータ走査アルゴリズムを可能にします。デフォルトでは、Unity はリフレクションを使用して型に対するプロパティを生成します。リフレクションによる方法では、プロパティバッグがまだ登録されていない場合、型ごとに一度だけ遅延してプロパティが生成されるため、便利です。
パフォーマンスを向上させるには、タイプに [Unity.Properties.GeneratePropertyBag] というタグを付けてコード生成をオプトインします。また、コード生成をアクティブにするには、アセンブリに [assembly: Unity.Properties.GeneratePropertyBagsForAssembly] というタグを付ける必要があります。コードが生成されたプロパティバッグは、ドメインがロードされるときに自動的に登録されます。
リフレクションとコード生成の両方のシナリオで、プロパティバッグは以下のプロパティを生成します。
[SerializeField]、[SerializeReference]、または [CreateProperty] でタグ付けされた private または internal フィールド[Unity.Properties.CreateProperty] でタグ付けされた public、private、または internal プロパティプロパティバッグは、[DontCreateProperty] でタグ付けされた public、private、または internal フィールドのプロパティを生成しません。
フィールドが読み取り専用の場合、またはプロパティが getter のみを持つ場合、生成されたプロパティは読み取り専用になります。
[Unity.Properties.CreateProperty(ReadOnly = true)] を使用して、生成したプロパティを読み取り専用にすることもできます。
利便性のために、シリアル化属性を使用してプロパティバッグにプロパティを作成する方法は、必ずしも推奨されるわけではありません。Unity のシリアル化システムはフィールドと自動プロパティに対してのみ動作するため、検証を実行したり、変更を効果的に反映したりすることは困難です。
以下の例では、Unity のシリアル化システムと Unity Properties システムを組み合わせています。
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 Properties は .NET のリフレクションを使用して、強く型指定されたプロパティバッグとプロパティを作成します。これにより、特定のコンテナ型に対して初めてプロパティをリクエストするときにパフォーマンスのオーバーヘッドが発生する可能性があります。
リフレクションによってフィールドメンバのプロパティを作成すると、これらのプロパティが IL2CPP ビルド内でガベージを割り当てることがあります。この割り当ては、System.Reflection.FieldInfo を直接使用することが原因で発生し、その結果、ボックス化を回避できなくなります。
リフレクションを避けるためには、コンパイル時にプロパティバッグをコード生成します。ただし、この最適化によってコンパイル時間が長くなる可能性があることに注意してください。アセンブリのコード生成を有効にするには、アセンブリに [Unity.Properties.GeneratePropertyBagsForAssemblyAttribute] のタグを付け、個々の型に [Unity.Properties.GeneratePropertyBagAttribute] のタグを付けます。プロパティバッグが internal および private のフィールドとプロパティにアクセスできるようにするには、型を partial にします。