SerializeReference mejoras en Unity 2021 LTS
En la última versión de LTS, la serialización polimórfica ofrece una mejor colaboración de usuarios y acceso a la API, además de un manejo más granular de los tipos que faltan.
En la última versión de LTS, la serialización polimórfica ofrece una mejor colaboración de usuarios y acceso a la API, además de un manejo más granular de los tipos que faltan.
Con el atributo SerializeReference , puede serializar un objeto asignado a un campo como referencia, en lugar de serializarlo por valor. Los objetos a los que se hace referencia se denominan "referencias administradas". Los campos con el atributo SerializeReference sirven para admitir polimorfismo y valores nulos; y, más recientemente, Unity 2021 LTS introdujo ID estables para referencias administradas, que brindan un manejo granular de tipos faltantes y acceso mejorado a la API. En este blog, compartimos más sobre estos cambios y cómo pueden beneficiarlo directamente.
Las referencias administradas se guardan dentro de los datos de serialización de su host, donde el host es un objeto de Unity (como una clase derivada de MonoBehaviour o ScriptableObject). Para ello, asignamos un ID único a cada objeto de referencia gestionado.
Un campo con el atributo SerializeReference se serializa guardando el ID del objeto al que se hace referencia. Las propias referencias administradas se guardan en una lista denominada ManagedReferenceRegistry, que se incluye dentro de los datos serializados del host.
En Unity 2019 y 2020 LTS, los ID se asignaron en el momento de guardar mediante un recorrido del contenido en profundidad. El principal inconveniente de este enfoque es que las pequeñas acciones, como reordenar los elementos de una matriz, pueden provocar un cambio significativo en el archivo afectado. Los grandes cambios dentro de los archivos podrían generar conflictos de fusión, que son difíciles de resolver cuando se trabaja en un entorno colaborativo.
Es por eso que introdujimos Stable ID. La identificación estable garantiza que una vez que se asigna a un objeto su propia identificación única, esa misma identificación se retiene a través de sucesivos ciclos de guardado y carga. En otras palabras, cambiar la asignación de campo de las referencias administradas en el host y luego volver a guardar, no alterará la ID.
Para ilustrar el valor de Stable ID, considere el siguiente ejemplo:
Este ejemplo crea una matriz de objetos de referencia administrados, poblados con instancias intercaladas de la clase Sandwich y Fruit. Puede ver el contenido de la matriz inspeccionando el archivo LunchBox1.asset.
Mover la primera entrada al final de la lista dará como resultado un cambio en el archivo de activos subyacente. Las siguientes capturas de pantalla de una herramienta de diferencias demuestran cuán simple es la diferencia de 2021.3, ya que los objetos en la matriz ahora tienen ID que son independientes del orden de la matriz.
2020.3:
2021.3:
Además de reducir los cambios dentro de los archivos de Unity, la función Stable ID está diseñada para abordar los desafíos comunes de colaboración. En versiones anteriores, dos usuarios que agregaban objetos de referencia administrados en el mismo host terminaban con el mismo ID, lo que dificultaba la fusión (especialmente porque más de un campo puede hacer referencia a un único objeto de referencia administrado). A partir de Unity 2021, los ID ahora están virtualmente garantizados para evitar dicho conflicto, ya que se generan en función de un hash de tiempo e información del sistema. Para escenarios más avanzados, incluso puede anular el sistema de asignación de ID predeterminado llamando a SerializationUtility.SetManagedReferenceIdForObject .
SerializeReference incluye soporte para polimorfismo, lo que significa que un campo se puede asignar a una instancia de una clase que se deriva del tipo de campo. De hecho, admitimos el tipo de campo como "System.Object", que es la clase base raíz de cada clase de C#. Pero esto abre la posibilidad de que a un proyecto compilado con éxito le falten las definiciones de clases que estaban disponibles anteriormente y que se habían guardado en un archivo de escena o de activos. En algunos casos, las clases pueden desaparecer cuando se eliminan los archivos de origen, se cambia el nombre de las clases o se mueven las clases a otro ensamblado.
Al cargar un objeto de host SerializedReference, se examina el nombre de tipo completamente calificado de cada objeto de referencia administrado y se debe resolver de nuevo a un tipo de clase válido para instanciarlo. En versiones anteriores de Unity, las clases faltantes podían poner todo el objeto "host" en un estado de error sin cargar ninguno de los objetos de referencia administrados válidos. Entonces, si tuviera un "host" con una matriz de 15 objetos de referencia administrados, pero no se pudiera resolver un solo objeto, entonces no vería ninguno de ellos en el Inspector. Se registraría un error en la consola, aunque el objeto host no se marcara visualmente como si estuviera en un estado de error cuando se inspeccionó, y todas las ediciones realizadas se descartarían silenciosamente.
En Unity 2021, ahora instanciamos todos los objetos de referencia administrados cargables y reemplazamos los que faltan por nulos. Esto brinda a los usuarios la oportunidad de ver más del estado del objeto host y facilitar la resolución de los tipos que faltan. Mientras tanto, si el tipo que falta se restaura mientras se carga el objeto host, la recarga de dominio desencadenada restaurará los objetos de referencia administrados y todos los campos que hacen referencia a él se actualizarán correctamente.
Este es un ejemplo de cómo aparecen los objetos a los que les faltan tipos en el Inspector:
En 2020.3, falta la clase Fruit, pero el Inspector no muestra ningún elemento de matriz y no hay indicios de un error:
En 2021.3, el Inspector le advierte que los objetos Fruit que faltan aparecen como entradas nulas, mientras que los objetos Sandwich siguen mostrándose:
Los mensajes de error en la consola relacionados con los tipos que faltan también se han actualizado para que sean menos repetitivos: simplemente identifican qué objetos del host tienen tipos que faltan.
Aquí hay un mensaje de error en 2020.3:
Compárelo con este mensaje de advertencia en 2021.3:
Al aprovechar esas mejoras en los ID, además de los cambios realizados en los objetos de referencia administrados en Prefabs, ahora se adhieren a esos objetos de referencia administrados. En el pasado, PropertyModifications apuntaba a campos en función de la ruta de la primera propiedad que conducía a ese campo. Esto significaba que si la ruta cambiaba (al reordenar una matriz, por ejemplo), PropertyModification perdería el rastro de la referencia administrada prevista y no se resolvería correctamente. A partir de Unity 2021, hay PropertyModifications que hacen referencia a objetos de referencia administrados mediante una ruta que incorpora el Stable ID, es decir, disabledReferences[12345].myString . Esto garantiza que un objeto de referencia administrado mantenga sus valores anulados, sin importar dónde lo mueva en el host.
Se agregó una nueva clase, SerializationUtility , a la API de Unity para exponer la funcionalidad relacionada con SerializeReference. Por ejemplo, SerializationUtility.ClearAllManagedReferencesWithMissingTypes() se puede usar para eliminar las referencias a los tipos que faltan, como eliminar el estado de advertencia de un host si no se planifica la recuperación de un tipo que falta.
Hemos perfeccionado la API para trabajar con referencias administradas en el contexto de CustomEditors, incluida la opción de acceso de lectura a SerializedProperty.managedReferenceValue .
La referencia para los nuevos métodos también ofrece código de muestra y hemos incorporado más detalles para los temas de referencia relacionados con la serialización.
Tus proyectos existentes que usan SerializeReference deberían cargarse sin problemas en la nueva versión de Unity, ya que el código de serialización es compatible con el formato de referencia administrado anterior. A menudo, el uso de SerializeReference no requiere un conocimiento profundo del concepto de ID estable o los nuevos métodos API. Sin embargo, incluso cuando se dejan "bajo el capó", estas mejoras son beneficiosas para el uso típico, especialmente en un entorno colaborativo.
Esperamos que este artículo lo anime a explorar más a fondo la función. A medida que nuestro equipo de serialización continúa mejorando las capacidades para todos los usuarios de Unity, apreciamos sus comentarios y debates continuos en este hilo del foro dedicado .