Que recherchez-vous ?
Engine & platform

Améliorations de SerializeReference dans le LTS pour Unity 2021

MARTIN BARRETTE Software Engineering Manager
Jul 11, 2022|11 Min
Améliorations de SerializeReference dans le LTS pour Unity 2021
Cette page a été traduite automatiquement pour faciliter votre expérience. Nous ne pouvons pas garantir l'exactitude ou la fiabilité du contenu traduit. Si vous avez des doutes quant à la qualité de cette traduction, reportez-vous à la version anglaise de la page web.

Dans la dernière version du LTS, la sérialisation polymorphe offre une meilleure collaboration entre les utilisateurs et un accès API, ainsi qu'une gestion plus granulaire des types manquants.

Avec l'attribut SerializeReference, vous pouvez sérialiser un objet assigné à un champ comme référence, au lieu de le sérialiser par valeur. Les objets référencés sont appelés « références gérées ». Les champs avec l'attribut SerializeReference servent à prendre en charge le polymorphisme et les valeurs null - et plus récemment, le LTS pour Unity 2021 a introduit des ID stables pour les références gérées, qui offrent une gestion granulaire des types manquants et un accès API amélioré. Dans ce blog, nous vous en dirons plus sur ces changements et sur la façon dont ils peuvent vous être directement bénéfiques.

ID stable

Les références gérées sont enregistrées dans les données de sérialisation de leur hôte, où l'hôte est un objet Unity (comme une classe dérivée de MonoBehaviour ou ScriptableObject). Pour ce faire, nous assignons un ID unique à chaque objet de référence géré.

Un champ avec l'attribut SerializeReference est sérialisé en enregistrant l'ID de l'objet référencé. Les références gérées elles-mêmes sont enregistrées dans une liste appelée ManagedReferenceRegistry, qui est incluse dans les données sérialisées de l'hôte.

Dans les LTS pour Unity 2019 et 2020, les identifiants étaient attribués au moindre instant grâce à un parcours approfondi du contenu. Le principal inconvénient de cette approche est que de petites actions, comme la réorganisation des éléments d'un tableau, peuvent entraîner un changement significatif dans le fichier affecté. Des modifications importantes dans les fichiers peuvent ainsi conduire à des conflits de fusion, difficiles à résoudre lorsque vous travaillez dans un environnement collaboratif.

C'est pourquoi nous avons introduit Stable ID. Stable ID garantit qu'une fois qu'un objet se voit attribuer son propre ID unique, ce même ID est conservé au cours des cycles de sauvegarde et de chargement successifs. En d'autres termes, changer l'assignation de champ des références gérées sur l'hôte, puis enregistrer à nouveau, ne modifiera pas l'ID.

Pour illustrer la valeur de Stable ID, considérons l'exemple suivant :

Sérialisation du code source

Cet exemple crée une gamme d'objets de référence gérés, remplis d'instances entrelacées de la classe Sandwich et Fruit. Vous pouvez afficher le contenu de la gamme en inspectant le fichier LunchBox1.asset.

Exemple d'inspecteur

Déplacer la première entrée à la fin de la liste entraînera une modification du fichier ressource sous-jacent. Les captures d'écran suivantes provenant d'un outil de différence montrent à quel point la différence par rapport à 2021.3 est simple, car les objets de la gamme ont désormais des ID indépendants de l'ordre de la gamme.

2020.3:

Commande de la gamme 2020.3 dans Unity

2021.3:

Commande de matrices 2021.3 dans Unity
Des ID uniques pour une collaboration fluide

En plus de réduire les modifications dans les fichiers Unity, la fonctionnalité Stable ID est conçue pour répondre aux défis de collaboration courants. Dans les versions précédentes, deux utilisateurs qui ajoutaient des objets de référence gérés sur le même hôte se retrouvaient avec le même ID, ce qui rendait difficile la fusion (d'autant plus qu'un seul objet de référence géré peut être référencé par plusieurs champs). À partir de Unity 2021, les ID sont désormais pratiquement garantis pour éviter un tel conflit, car ils sont générés en fonction d'un hash de temps et d'informations système. Pour les scénarios plus avancés, vous pouvez même remplacer le système d'attribution d'ID par défaut en appelant SerializationUtility.SetManagedReferenceIdForObject.

Manque à l'appel

SerializeReference inclut la prise en charge du polymorphisme, ce qui signifie qu'un champ peut être assigné à une instance d'une classe dérivée du type de champ. En fait, nous prenons en charge le type de champ comme « System.Object » qui est la classe de base racine de chaque classe C#. Mais cela ouvre la possibilité qu'un projet compilé avec succès manque les définitions des classes qui étaient auparavant disponibles et avaient été enregistrées dans une scène ou un fichier ressource. Dans certains cas, les classes peuvent disparaître lorsque les fichiers sources sont supprimés, renommés ou déplacés vers un autre assemblage.

Lors du chargement d'un objet hôte SerializedReference, le nom de type complet de chaque objet de référence géré est examiné et doit être résolu à nouveau en un type de classe valide pour l'instancier. Dans les versions précédentes de Unity, les classes manquantes pouvaient mettre l'ensemble de l'objet « hôte » dans un état d'erreur sans charger aucun des objets de référence gérés valides. Ainsi, si vous aviez un « hôte » avec une gamme de 15 objets de référence gérés, mais qu'un seul objet ne pouvait pas être résolu, alors vous n'en verrez aucun dans l'Inspector. Il y aurait une erreur enregistrée dans la console, même si l'objet hôte n'était pas visuellement marqué comme étant dans un état d'erreur lors de l'inspection, et toutes les modifications effectuées seraient rejetées silencieusement.

Dans Unity 2021, nous instancions désormais tous les objets de référence gérés chargeables et remplaçons par null ceux qui manquent. Cela permet aux utilisateurs de voir plus en détail l'état de l'objet hôte et de faciliter la résolution des types manquants. Pendant ce temps, si le type manquant est restauré pendant le chargement de l'objet hôte, alors le rechargement de domaine déclenché restaurera les objets de référence gérés, et tous les champs le référençant seront correctement mis à jour.

Voici un exemple de la façon dont les objets avec des types manquants apparaissent dans l'Inspector :

Dans la version 2020.3, la classe Fruit est manquante, mais l'Inspector n'affiche aucun élément de tableau et rien n'indique une erreur :

Dans la version 2021.3, l'Inspector vous avertit que les objets Fruit manquants apparaissent comme des entrées null, alors que les objets Sandwich continuent à être affichés :

Les messages d'erreur dans la console liés aux types manquants ont également été mis à jour afin qu'ils soient moins répétitifs. Ils identifient simplement les objets hôtes ayant des types manquants.

Voici un message d'erreur dans la version 2020.3 :

Comparez-le à ce message d'avertissement dans la version 2021.3 :

Prefabs

L'exploitation de ces améliorations des ID, ainsi que des modifications apportées aux objets de référence gérés dans les prefabs reste désormais collée à ces objets de référence gérés. Auparavant, PropertyModifications ciblait les champs en fonction du premier chemin de propriété menant à ce champ. Cela signifiait que si le chemin changeait (en réordonnant un tableau, par exemple), alors PropertyModification perdait la trace de la référence gérée prévue et ne parvenait pas à se résoudre correctement. Depuis Unity 2021, il existe des PropertyModifications qui référencent les objets de référence gérés à l'aide d'un chemin incorporant l'ID Stable, c'est-à-dire managedReferences[12345].myString. Cela garantit qu'un objet de référence géré conserve ses valeurs annulées, quel que soit l'endroit où vous le déplacez sur l'hôte.

Prise en charge améliorée des API

Une nouvelle classe, SerializationUtility, a été ajoutée à l'API Unity pour exposer les fonctionnalités liées à SerializeReference. Par exemple, SerializationUtility.ClearAllManagedReferencesWithMissingTypes() peut être utilisé pour supprimer les références aux types manquants, comme la suppression de l'état d'avertissement d'un hôte si aucune récupération n'est prévue pour un type manquant.

Nous avons amélioré l'API pour qu'elle fonctionne avec des références gérées dans le contexte des éditeurs personnalisés, y compris l'option d'accès en lecture à SerializedProperty.managedReferenceValue.

Les références pour les nouvelles méthodes proposent également des exemples de code, et nous avons intégré plus de détails pour les sujets de référence liés à la sérialisation.

Vos projets existants qui utilisent SerializeReference devraient charger en douceur dans la nouvelle version de Unity, car le code de sérialisation est compatible avec l'ancien format de référence géré. Souvent, l'utilisation de SerializeReference ne nécessite pas une connaissance approfondie du concept Stable ID, ni des nouvelles méthodes API. Cependant, même lorsqu'elles sont laissées « sous le capot », ces améliorations sont bénéfiques pour un usage typique, en particulier dans un environnement collaboratif.

Nous espérons que cet article vous encouragera à explorer davantage cette fonctionnalité. Alors que notre équipe chargée des sérialisations continue d'améliorer les capacités de tous les utilisateurs Unity, nous vous remercions de vos commentaires et discussions actuels sur ce forum dédié.