что такое serializefield в unity

SerializeField

class in UnityEngine

Success!

Thank you for helping us improve the quality of Unity Documentation. Although we cannot accept all submissions, we do read each suggested change from our users and will make updates where applicable.

Submission failed

For some reason your suggested change could not be submitted. Please try again in a few minutes. And thank you for taking the time to help us improve the quality of Unity Documentation.

Description

Force Unity to serialize a private field.

When Unity serializes your scripts, it only serializes public fields. If you also want Unity to serialize your private fields you can add the SerializeField attribute to those fields.

The serialization system can do the following:

Serializable types

Unity can serialize fields of the following types:

For more information on serialization, see Script Serialization.

Note: If you put one element in a list (or array) twice, when the list gets serialized, you’ll get two copies of that element, instead of one copy being in the new list twice.

Note: If you want to serialize a custom Struct field, you must give the Struct the [System.Serializable] attribute.

Hint: Unity won’t serialize Dictionary, however you could store a List<> for keys and a List<> for values, and sew them up in a non serialized dictionary on Awake(). This doesn’t solve the problem of when you want to modify the dictionary and have it «saved» back, but it is a handy trick in a lot of other cases.

Is something described here not working as you expect it to? It might be a Known Issue. Please check with the Issue Tracker at issuetracker.unity3d.com.

Copyright ©2021 Unity Technologies. Publication Date: 2021-11-12.

Источник

SerializeField

class in UnityEngine

Успех!

Благодарим вас за то, что вы помогаете нам улучшить качество документации по Unity. Однако, мы не можем принять любой перевод. Мы проверяем каждый предложенный вами вариант перевода и принимаем его только если он соответствует оригиналу.

Ошибка внесения изменений

По определённым причинам предложенный вами перевод не может быть принят. Пожалуйста попробуйте снова через пару минут. И выражаем вам свою благодарность за то, что вы уделяете время, чтобы улучшить документацию по Unity.

Описание

Force Unity to serialize a private field.

You will almost never need this. When Unity serializes your scripts, it will only serialize public fields. If in addition to that you also want Unity to serialize one of your private fields you can add the SerializeField attribute to the field.

The serialization system used can do the following:

— CAN serialize public nonstatic fields (of serializable types)
— CAN serialize nonpublic nonstatic fields marked with the [SerializeField] attribute.
— CANNOT serialize static fields.
— CANNOT serialize properties.

Your field will only serialize if it is of a type that Unity can serialize:

Serializable types are:

— All classes inheriting from UnityEngine.Object, for example GameObject, Component, MonoBehaviour, Texture2D, AnimationClip.
— All basic data types like int, string, float, bool.
— Some built-in types like Vector2, Vector3, Vector4, Quaternion, Matrix4x4, Color, Rect, LayerMask.
— Arrays of a serializable type
— List of a serializable type)
— Enums
— Structs

Note: if you put one element in a list (or array) twice, when the list gets serialized, you’ll get two copies of that element, instead of one copy being in the new list twice.

Hint: Unity won’t serialize Dictionary, however you could store a List<> for keys and a List<> for values, and sew them up in a non serialized dictionary on Awake(). This doesn’t solve the problem of when you want to modify the dictionary and have it «saved» back, but it is a handy trick in a lot of other cases.

For UnityScript users: Fields in c# is a script variable in UnityScript, and [SerializeField] becomes @SerializeField. [Serializable] on a class becomes @script Serializable in a UnityScript.

Источник

Serialize Reference в Unity

Всем добрый день. Эта статья про относительно новую фичу Serialize Reference. Появилась она в 2019 версии.

Оглавление:

Что это такое и зачем оно нужно

Как работать с этим

В данных примерах под типом object скрывается сериализация ExampleFirst и ExampleSecond.

Плюсы

Это отвязка от монобеха

Читайте также:  что делать если начались месячные а таблетки еще не закончились

Отказ от изменения реализации поведения через интерфейс и множество реализаций через компоненты

Это хранение данных в одном листе, вместо постоянного раздувания количества листов ради новых данных

Никаких кастомных решений для редактора. Отображение экземпляров происходит за счёт стандартных решений юнити.

Минусы

При изменении имени и неймспейса, ломается сериализация. Для того чтобы починить сериализацию после изменения имении и неймспейса, требуется использовать movefromattribute в котором будет указано, как раньше назывался данный тип, и где находился

Юнитехи не предоставили удобного инструментария для работы в редакторе из под капота (Будет описано ниже)

Как с этим работать

Мы теперь знаем что наше любимое юнити умеет сериализовывать абстрактные поля, но как заставить всё это удобно работать?

Суть в том, что редактор сериализует экземпляр, а не поле. И если в него ничего не было вложено, то собственно ему и нечего сериализовывать и отображать вам. В случае обычного SerializeField, редактор автоматически инициализирует ваше поле, даже если вы не укажете это в коде

Но как вложить экземпляр в данное поле? Дефолтными способами из коробки только через дефолтную инициализацию. Юнитеки не предоставили удобного инструментария для работы с данными полями. Единственное что вам дали, это 3 поля у данных типа SerializeProperty:

Для отрисовки данных экзмепляров юнити использует стандартную механиху PropertyDrawer. Т.е. если вам нужно будет заоверрайдить отрисовку, либо сделать декорацию с помощью PropertyAttribute, то это всё также работает в SerializeReference.

Для инициализации данных полей можно писать кастомный инстурментарий используя поля SerializeProperty описанные выше, либо использовать данный [ассет](https://github.com/elmortem/serializereferenceeditor)

Самое важное ещё понимать с чем это сериализация может работать, а с чем нет. Данная шпаргалка есть в доке [юнитехов](https://docs.unity3d.com/ScriptReference/SerializeReference.html)

Тип поля не должен наследоваться от UnityEngine.Object

Тип поля может быть абстрактным классом/интерфейсом

Применение аттрибута SerializeReference к листу/массиву приводит его применение ко всем его элементам. Т.е. List работает.

Референсы данных полей не могут быть у разных UnityEngine.Object. Т.е. если вы присваивали в редакторе один и тот же экземпляр, то после десериализации это будут разные экземпляры но с одним и тем же наполнением.

Тип данных который пытаетесь сериализовать, должен быть почемен атрибутом [Serializable]

Примеры

Я также для себя пытался реализовывать подобную фичу, но без некоторых элементов. Ничего сложного в этом нет. Код как это легко реализовать есть ниже:

Источник

Script Serialization

Serialization of “things” is at the very core of Unity. Many of our features build ontop of the serialization system:

Inspector window. The inspector window doesn’t talk to the C# api to figure out what the values of the properties of whatever it is inspecting is. It asks the object to serialize itself, and then displays the serialized data.

Prefabs. Internally, a prefab is the serialized data stream of one (or more) game objects and components. A prefab instance is a list of modifications that should be made on the serialized data for this instance. The concept prefab actually only exists at editor time. The prefab modifications get baked into a normal serialization stream when Unity makes a build, and when that gets instantiated, the instantiated gameobjects have no idea they were a prefab when they lived in the editor.

Loading. Might not seem surprising, but backwards compatible loading is a system that is built on top of serialization as well. In-editor yaml loading uses the serialization system, but also the runtime loading of scenes, assets and assetbundles uses the serialization system.

Now you’d say that none of this very much concerns you, you’re just happy that it works and want to get on with actually creating some content.

Where it will concern you is that we use this same serializer to serialize MonoBehaviour components, which are backed by your scripts. Because of the very high performance requirements that the serializer has, it does not in all cases behave exactly like what a c# developer would expect from a serializer. In this part of the docs we’ll describe how the serializer works, and some best practices on how to make best use of it.

What does a field of my script need to be in order to be serialized?

Which fieldtypes can we serialize?

What are these situations where the serializer behaves differently from what I expect?

Custom classes behave like structs

If you populate the animals array with three references to a single Animal object, in the serialization stream, you will find 3 objects. when it’s deserialized, there are now three different objects. If you need to serialize a complex object graph with references, you cannot rely on Unity’s serializer doing that all automagically for you, and have to do some work to get that object graph serialized yourself. See the example below on how to serialize things Unity doesn’t serialize by itself.

Читайте также:  что делать если человек на вас орет

No support for null for custom classes

Pop quiz. How many allocations are made when deserializing a MonoBehaviour that uses this script:

It wouldn’t be strange to expect 1 allocation. That of the Test object. It also wouldn’t be strange to expect 2 allocations. One for the Test Object, one for a Trouble object. The correct answer is 729. The serializer does not support null. If it serializes an object, and a field is null, we just instantiate a new object of that type, and serialize that. Obviously this could lead to infinite cycles, so we have a relatively magical depth limit of 7 levels. At that point we just stop serializing fields that have types of custom classes/structs and lists and arrays.

Since so many of our subsystems build on top of the serialization system, this unexpectedly large serialization stream for the Test monobehaviour will cause all these subsystems to perform more slowly than necessary. When we investigate performance problems in customer projects, almost always do we find this problem. We added a warning for this situation in Unity 4.5.

No support for polymorphism

if you have a public Animal[] animals and you put in an instance of a dog, a cat and a giraffe, after serialization, you will have three instances of Animal.

One way to deal with this limitation is to realize that it only applies to “custom classes”, which get serialized inline. References to other UnityEngine.Objects get serialized as actual references, and for those polymorphism does actually work. You would make a ScriptableObject derived class or another MonoBehaviour derived class, and reference that. The downside of that is that you need to store that monobehaviour or scriptable object somewhere, and cannot serialize it inline nicely.

The reason for these limitations is that one of the core foundations of the serialization system is that the layout of the datastream for an object is known ahead of time, and depends on the types of the fields of the class, instead of what happens to be stored inside the fields.

I want to serialize something that Unity’s serializer doesn’t support. What do I do?

In many cases the best approach is to use serialization callbacks. They allow you to be notified before the serializer reads data from your fields and after it is done writing to them. You can use this to have a different representation of your hard-to-serialize data at runtime than when you actually serialize. You would use these to transform your data into something Unity understands right before unity wants to serialize it, and you use it to transform the serialized form back into the form you like to have your data in at runtime right after unity has written the data to your fields.

Suppose you want to have a tree datastructure. If you let Unity directly serialize the data structure, the “no support for null” limitation would cause your datastream to become very big, leading to performance degratations in many systems:

Instead, you tell Unity not to serialize the tree directly, and you make a seperate field to store the tree in a serialized format, suited for unity’s serializer:

Beware that the serializer, including these callbacks coming from the serializer usually happen not on the main thread, so you are very limited in what you can do in terms of invoking Unity API. You can however to the necessary data transformations do get your data from a non-unity-serializer-friendly format to a unity-serializer-friendly-format.

Script serialization errors

When scripts call the Unity API from constructors or field initializers, or during deserialization (loading), they can trigger errors. This section demonstrates the poor practise that causes these errors.

Читайте также:  что значит прикинься киса песиком

In Unity 5.4 these errors do not, in most cases, throw a managed exception, and do not interrupt the execution flow of your scripts. This eases the process of upgrading your project to Unity 5.4. However, these errors will throw a managed exception in subsequent releases of Unity. You should therefore fix any errors as soon as possible when upgrading to 5.4.

Calling Unity API from constructor or field initializers

When Unity creates an instance of a MonoBehaviour or ScriptableObject derived class, it calls the default constructor to create the managed object. This happens before entering the main loop, and before the scene has been fully loaded. Field initializers are also called from the default constructor of a managed object. In general, do not call the Unity API from a constructor, as this is unsafe for the majority of the Unity API.

Examples of poor practice:

Both these cases generate the error message: “Find is not allowed to be called from a MonoBehaviour constructor (or instance field initializer), call in in Awake or Start instead.”

Calling Unity API during deserialization

When Unity loads a scene, it recreates the managed objects from the saved scene and populates them with the saved values (deserializing). In order to create the managed objects, call the default constructor for the objects. If a field referencing an object is saved (serialized) and the object default constructor calls the Unity API, you will get an error when loading the scene. As with the previous error, it is not yet in the main loop and the scene is not fully loaded. This is considered unsafe for the majority of the Unity API.

Example of poor practice:

This generates the error: “Find is not allowed to be called during serialization, call it from Awake or Start instead.”

Источник

Нативная сериализация и её подводные камни

Сегодня я хотел бы камень за камушком разобрать механизм сериализации в Unity и показать вам с чем его едят, а с чем есть категорически не стоит.

Что такое сериализация?

Сериализация классов

Первый способ заключается в том, чтобы добавить к нашему классу атрибут [System.Serializable]. Кратко описать функционал этого способа можно как «я сохраню значения полей».

В чем же их отличие?
Предположим, что мы наследуем несколько классов от уже созданного нами ItemInfo

В таком случае, чтобы хранить список совместно, мы будем использовать конструкцию, подобную такой:

Сериализация через наследование от ScriptableObject ===

Плюсы:
* Экземпляры сохраняют ссылки после ребилда
* Отлично подходят для замкнутых и рекурсивных систем

Сериализация через атрибут [Serializable] ===

Минусы:
* Ссылочность часто стирается при ребилде
* Та ссылочность, которая остается реализована весьма костыльно
* Generic-типы не сериализуются

Для того, чтобы понять почему происходит потеря ссылок, нам нужно понять сам алгоритм сериализации.
Для обычных классов он такой:

У данного способа есть ряд грубых багов, которые могут вызывать краш Unity.
Взгляните на следующую конструкцию:

Данный код, несмотря на всю его кажущуюся безобидность способен заставить разработчика часами убиваться в дебаге. Чтобы получить тот «несбыточный вариант», достаточно написать код подобно следующему:

Сериализация полей

Я намеренно начал говорить про сериализацию классов, несмотря на то, что объяснение сериализации полей выглядит более простым. Но теперь, ознакомившись с функционалом сериализации классов можно сделать некоторые уточнения.

Бывают случаи, при которых поле должно быть сериализовано, но не должно отмечаться в инспекторе. Для этих целей применяют атрибут [HideInInspector]:

Случается, что вам нужно наоборот избежать сериализации поля с доступом public. Для этих целей есть атрибут [NonSerialized]:

Сериализацию поддерживают не все поля. Вы не сможете сериализовать:

Что делать с классами которые не сериализуются?

Часто среди стандартных библиотек Unity встречаются классы, которые не сохраняются и не могут быть нами отредактированы. Например к таким типам относятся типы Type, FieldInfo, MethodInfo, которые могут пригодиться при работе с рефлексией.
Однако, у большинства подобных классов есть свои «рычаги» для восстановления.
Например:

Таким образом, такие данные реально закешировать.
Пример сериализации для типа Type:

Что осталось?

Update: написал сериализацию функторов. Прошу любить и жаловать.

Источник

Строительный портал