Version: 2021.2
言語: 日本語

SerializeReference

class in UnityEngine

マニュアルに切り替える

説明

Instruct Unity to serialize a field as a reference.

By default when Unity serializes an object it serializes all fields as value types, unless the field type derives from UnityEngine.Object.

Decorating a field with [SerializeReference] instructs Unity to serialize the field 'by reference' instead of 'by value'. That makes it possible to serialize reference-based topologies, like graphs, and in the case of polymorphism the full specialized object will be serialized properly. Using SerializeReference adds extra overhead, so it should only be used when regular 'by value' serialization is not sufficient.

The objects serialized with the SerializeReference attribute are referred to as "Managed References". The MonoBehaviour, ScriptableObject or other "host" object that contains the [SerializeReference] fields associates a unique Id with each managed reference. This Id is typically automatically generated, but it can be specified using SerializationUtility.SetManagedReferenceIdForObject.

Referenced objects cannot be shared between UnityEngine.Object instances. For example, two MonoBehaviours cannot share an object that is serialized by reference. Cloning an object that hosts managed references will create a copy of all the managed reference objects.

An alternative to [SerializeReference] is to use ScriptableObject instead. ScriptableObjects have good performance and permit sharing data between MonoBehaviours.

Notes:
- The type of the object assigned to the field should be a class decorated with the Serializable attribute.
- The field value can be null.
- The field value can be be a class derived from the field type.
- The field type can be an interface, or abstract.
- The types 'System.Object', 'List<System.Object>' and 'System.Object[]' are supported for the field type.
- Neither the field type, nor the assigned object, can be of a type that specializes UnityEngine.Object.
- Field type cannot be a specific specialization of a generic type(inflated type).
- Generic Lists and array fields decorated with [SerializeReference] apply the attribute to the elements of the list/array, not the list/array instance itself.
- Fields on referenced objects cannot be animated.

See Also: SerializedProperty.managedReferenceValue, MonoBehaviour, SerializationUtility

using System;
using UnityEngine;

public class SerializeReferencePolymorphismExample : MonoBehaviour { [Serializable] public class Base { public int m_Data = 1; }

[Serializable] public class Apple : Base { public string m_Description = "Ripe"; }

[Serializable] public class Orange : Base { public bool m_IsRound = true; }

// Use SerializeReference if this field needs to hold both // Apples and Oranges. Otherwise only m_Data from Base object would be serialized [SerializeReference] public Base m_Item = new Apple();

[SerializeReference] public Base m_Item2 = new Orange();

// Use by-value instead of SerializeReference, because // no polymorphism and no other field needs to share this object public Apple m_MyApple = new Apple(); }
using System;
using System.Text;
using UnityEngine;

public class SerializeReferenceLinkedListExample : MonoBehaviour { // This example shows a linked list structure with a single int per Node. // This would be much more efficiently represented using a List<int>, without any SerializeReference needed. // But it demonstrates an approach that can be extended for trees and other more advanced graphs

[Serializable] public class Node { // This field must use serialize reference so that serialization can store // a reference to another Node object, or null. By-value // can never properly represent this sort of self-referencing structure. [SerializeReference] public Node m_Next = null;

public int m_Data = 1; }

[SerializeReference] public Node m_Front = null;

// Points to the last node in the list. This is an // example of a having more than one field pointing to a single Node // object, which cannot be done with "by-value" serialization [SerializeReference] public Node m_End = null;

SerializeReferenceLinkedListExample() { AddEntry(1); AddEntry(3); AddEntry(9); AddEntry(81); PrintList(); }

private void AddEntry(int data) { if (m_Front == null) { m_Front = new Node() {m_Data = data}; m_End = m_Front; } else { m_End.m_Next = new Node() {m_Data = data}; m_End = m_End.m_Next; } }

private void PrintList() { var sb = new StringBuilder(); sb.Append("Link list contents: "); var position = m_Front; while (position != null) { sb.Append(" Node data " + position.m_Data).AppendLine(); position = position.m_Next; } Debug.Log(sb.ToString()); } }
using System;
using System.Collections.Generic;
using UnityEngine;

public interface IShape {}

[Serializable] public class Cube : IShape { public Vector3 size; }

[Serializable] public class Thing { public int weight; }

[ExecuteInEditMode] public class BuildingBlocks : MonoBehaviour { [SerializeReference] public List<IShape> inventory;

[SerializeReference] public System.Object bin;

[SerializeReference] public List<System.Object> bins;

void OnEnable() { if (inventory == null) { inventory = new List<IShape>() { new Cube() {size = new Vector3(1.0f, 1.0f, 1.0f)} }; Debug.Log("Created list"); } else Debug.Log("Read list");

if (bins == null) { // This is supported, the 'bins' serialized field is declared as a collection, with each entry as a reference. bins = new List<System.Object>() { new Cube(), new Thing() }; }

if (bin == null) { // !! DO NOT USE !! // Although, this is syntaxically correct, it is NOT supported as a valid serialization construct because the 'bin' serialized field is declared as holding a single reference type. bin = new List<System.Object>() { new Cube() }; } } }