Engine & platform

SerializeReference-Verbesserungen in Unity 2021 LTS

MARTIN BARRETTE Software Engineering Manager
Jul 11, 2022|11 Min.
SerializeReference-Verbesserungen in Unity 2021 LTS
Diese Website wurde aus praktischen Gründen für Sie maschinell übersetzt. Die Richtigkeit und Zuverlässigkeit des übersetzten Inhalts kann von uns nicht gewährleistet werden. Sollten Sie Zweifel an der Richtigkeit des übersetzten Inhalts haben, schauen Sie sich bitte die offizielle englische Version der Website an.

In der neuesten LTS-Version bietet die polymorphe Serialisierung eine verbesserte Benutzerzusammenarbeit und API-Zugriff sowie einen detaillierteren Umgang mit fehlenden Typen.

Mit dem Attribut SerializeReference können Sie ein Objekt serialisieren, das einem Feld als Referenz zugewiesen ist, anstatt es nach Wert zu serialisieren. Die Objekte, die referenziert werden, werden als „verwaltete Referenzen“ bezeichnet. Felder mit dem Attribut SerializeReference dienen zur Unterstützung von Polymorphie und Null Werten – und vor kurzem hat Unity 2021 LTS stabile IDs für verwaltete Referenzen eingeführt, die einen detaillierten Umgang mit fehlenden Typen und einen besseren API Zugriff ermöglichen. In diesem Blog teilen wir mehr über diese Änderungen und darüber, wie sie Ihnen direkt nutzen können.

Stabile ID

Verwaltete Referenzen werden in den Serialisierungsdaten des Hosts gespeichert, wobei der Host ein Unity Objekt ist (z. B. eine Klasse, die von MonoBehaviour oder ScriptableObject abgeleitet ist). Dazu weisen wir jedem verwalteten Referenzobjekt eine eindeutige ID zu.

Ein Feld mit dem Attribut SerializeReference wird serialisiert, indem die ID des referenzierten Objekts gespeichert wird. Die verwalteten Referenzen selbst werden in einer Liste namens ManagedReferenceRegistry gespeichert, die in den serialisierten Daten des Hosts enthalten ist.

In Unity 2019 und 2020 LTS wurden IDs über ein Deep-First-Durchlaufen der Inhalte zeitsparend zugewiesen. Der Hauptnachteil dieses Ansatzes besteht darin, dass kleine Aktionen, wie das Neuordnen der Elemente eines Arrays, zu einer erheblichen Veränderung der betroffenen Datei führen können. Große Änderungen innerhalb der Dateien können dadurch zu Merging-Konflikten führen, die bei der Arbeit in einer kollaborativen Umgebung nur schwer zu lösen sind.

Deshalb haben wir Stable ID eingeführt. Stabile ID stellt sicher, dass, sobald einem Objekt eine eigene eindeutige ID zugewiesen wurde, diese ID durch aufeinanderfolgende Speicher- und Ladezyklen beibehalten wird. Mit anderen Worten, die Feldzuweisung von verwalteten Referenzen auf dem Host zu ändern und dann wieder zu speichern, ändert nichts an der ID.

Zur Veranschaulichung des Werts der Stable-ID betrachten Sie das folgende Beispiel:

Serialisieren Sie Quellcode

In diesem Beispiel wird ein Array verwalteter Referenzobjekte erstellt, das mit verschachtelten Instanzen der Klasse Sandwich und Fruit gefüllt ist. Sie können den Inhalt des Arrays anzeigen, indem Sie die Datei LunchBox1.asset inspizieren.

Musterinspektor

Das Verschieben des ersten Eintrags an das Ende der Liste führt zu einer Änderung der zugrunde liegenden Asset-Datei. Die folgenden Screenshots aus einem Diff-Tool zeigen, wie einfach der Unterschied zu 2021.3 ist, da die Objekte im Array jetzt IDs haben, die unabhängig von der Array-Reihenfolge sind.

2020.3:

2020.3 Array-Bestellung in Unity

2021.3:

2021.3 Array-Bestellung in Unity
Einzigartige IDs für eine reibungslose Zusammenarbeit

Neben der Reduzierung von Änderungen innerhalb von Unity-Dateien wurde die Funktion „Stable ID“ auf gängige Herausforderungen bei der Zusammenarbeit ausgelegt. In früheren Versionen erhielten zwei Benutzer, die verwaltete Referenzobjekte auf demselben Host hinzugefügt haben, dieselbe ID, was das Merging erschwerte (zumal ein einzelnes verwaltetes Referenzobjekt von mehr als einem Feld referenziert werden kann). Ab Unity 2021 können IDs einen solchen Konflikt praktisch vermeiden, da sie auf Basis eines Hashs aus Zeit- und Systeminformationen generiert werden. Für fortgeschrittenere Szenarien können Sie sogar das Standard-ID-Zuweisungssystem überschreiben, indem Sie SerializationUtility.SetManagedReferenceIdForObject aufrufen.

Fehlende Typbehandlung

SerializeReference bietet Unterstützung für Polymorphie, was bedeutet, dass ein Feld einer Instanz einer Klasse zugewiesen werden kann, die sich vom Feldtyp ableitet. Tatsächlich unterstützen wir den Feldtyp als „System.Object“, also die Basisklasse jeder C#-Klasse. Dies eröffnet jedoch die Möglichkeit, dass ein erfolgreich kompiliertes Projekt die zuvor verfügbaren Klassendefinitionen verfehlt, die in einer Szene oder Asset-Datei gespeichert wurden. In manchen Fällen können Klassen fehlen, wenn Quelldateien entfernt, Klassen umbenannt oder Klassen in eine andere Assembly verschoben werden.

Beim Laden eines SerializedReference-Hostobjekts wird der voll qualifizierte Typname jedes verwalteten Referenzobjekts untersucht und muss zur Instanziierung in einen gültigen Klassentyp zurück aufgelöst werden. In früheren Versionen von Unity konnten fehlende Klassen das gesamte Hostobjekt in einen Fehlerzustand versetzen, ohne eines der gültigen verwalteten Referenzobjekte zu laden. Wenn Sie also einen „Host“ mit einem Array von 15 verwalteten Referenzobjekten hätten, aber ein einzelnes Objekt nicht aufgelöst werden konnte, würden Sie keines davon im Inspector sehen. Es wurde ein Fehler in der Konsole protokolliert – obwohl das Hostobjekt bei der Prüfung nicht visuell als in einem Fehlerzustand markiert wurde – und alle vorgenommenen Bearbeitungen wurden stillschweigend verworfen.

In Unity 2021 instanziieren wir jetzt alle ladbaren verwalteten Referenzobjekte und ersetzen die fehlenden durch Null. Dies gibt Nutzern die Möglichkeit, mehr vom Status des Hostobjekts zu sehen und die Auflösung fehlender Typen zu erleichtern. Wenn der fehlende Typ während des Ladens des Hostobjekts wiederhergestellt wird, werden die verwalteten Referenzobjekte durch das ausgelöste Domain Reload wiederhergestellt und alle Felder, die darauf verweisen, ordnungsgemäß aktualisiert.

Dies ist ein Beispiel dafür, wie Objekte mit fehlenden Typen im Inspector angezeigt werden:

In 2020.3 fehlt die Fruit-Klasse, aber der Inspector zeigt keine Array-Elemente und es gibt keine Hinweise auf einen Fehler:

In 2021.3 warnt Sie der Inspector, dass die fehlenden Fruit-Objekte als Null-Einträge erscheinen, während die Sandwich-Objekte weiterhin angezeigt werden:

Die Fehlermeldungen in der Konsole, die sich auf fehlende Typen beziehen, wurden ebenfalls aktualisiert, sodass sie weniger repetitiv sind – sie identifizieren einfach, welche Hostobjekte fehlende Typen haben.

Hier ist eine Fehlermeldung in 2020.3:

Vergleichen Sie es mit dieser Warnmeldung in 2021.3:

Prefabs

Die Nutzung dieser Verbesserungen an IDs und die Änderungen an verwalteten Referenzobjekten in Prefabs bleiben jetzt bei diesen verwalteten Referenzobjekten. In der Vergangenheit zielten PropertyModifications auf Felder ab, die auf dem ersten Eigenschaftspfad basieren, der zu diesem Feld führt. Das bedeutete, dass bei einer Änderung des Pfads (z. B. durch Neuanordnung eines Arrays) die PropertyModifikation den Überblick über die vorgesehene verwaltete Referenz verliert und sich nicht richtig auflöst. Seit Unity 2021 gibt es PropertyModifications, die verwaltete Referenzobjekte über einen Pfad referenzieren, der die Stable-ID enthält, d. h. managedReferences[12345].myString. Dadurch wird sichergestellt, dass ein verwaltetes Referenzobjekt seine übergeordneten Werte beibehält, unabhängig davon, wohin Sie es auf dem Host verschieben.

Verbesserte API Unterstützung

Die Unity API wurde um eine neue Klasse, SerializationUtility, erweitert, um Funktionen im Zusammenhang mit SerializeReference freizulegen. SerializationUtility.ClearAllManagedReferencesWithMissingTypes() kann beispielsweise verwendet werden, um Referenzen auf fehlende Typen zu entfernen, z. B. um den Warnzustand von einem Host zu entfernen, wenn keine Wiederherstellung für einen fehlenden Typ geplant ist.

Wir haben die API für die Arbeit mit verwalteten Referenzen im Kontext von CustomEditors verbessert, einschließlich der Option für Lesezugriff auf SerializedProperty.managedReferenceValue.

Die Referenz für die neuen Methoden enthält auch Beispielcode, und wir haben die Referenzthemen zur Serialisierung detaillierter aufgenommen.

Ihre bestehenden Projekte, die SerializeReference verwenden, sollten in der neuen Version von Unity reibungslos geladen werden, da der Serialisierungscode mit dem älteren verwalteten Referenzformat kompatibel ist. Oftmals erfordert die Verwendung von SerializeReference keine detaillierten Kenntnisse des Stable ID-Konzepts oder der neuen API Methoden. Doch auch wenn diese Verbesserungen „unter der Haube“ bleiben, sind sie für die typische Verwendung von Vorteil, insbesondere in einer kollaborativen Umgebung.

Wir hoffen, dass dieser Artikel Sie dazu ermutigt, die Funktion weiter zu erkunden. Da unser Serialisierungsteam die Funktionen für alle Unity Nutzer kontinuierlich erweitert, freuen wir uns über Ihr kontinuierliches Feedback und Ihre Diskussion zu diesem dedizierten Forums-Thread.