SerializeField
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 <a>try again</a> 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.
Unity serializes all your script components, reloads the new assemblies, and recreates your script components from the serialized versions. This serialization is done with an internal Unity serialization system; not with .NET’s serialization functionality.
The serialization system can do the following:
- CAN serialize public non-static fields (of serializable types)
- CAN serialize nonpublic non-static fields marked with the SerializeField attribute.
- CANNOT serialize static fields.
- CANNOT serialize properties.
Serializable types
Unity can serialize fields of the following types:
- All classes inheriting from UnityEngine.Object, for example GameObject, Component, MonoBehaviour, Texture2D, AnimationClip.
- All basic data types, such as int, string, float, bool.
- Some built-in types, such as Vector2, Vector3, Vector4, Quaternion, Matrix4x4, Color, Rect, LayerMask.
- Arrays of a serializable type
- Lists of a serializable type
- Enums
- Structs
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. See ISerializationCallbackReceiver for an example.
SerializeField
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 <a>try again</a> 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.
Unity serializes all your script components, reloads the new assemblies, and recreates your script components from the serialized versions. This serialization is done with an internal Unity serialization system; not with .NET’s serialization functionality.
The serialization system can do the following:
- CAN serialize public non-static fields (of serializable types)
- CAN serialize nonpublic non-static fields marked with the SerializeField attribute.
- CANNOT serialize static fields.
- CANNOT serialize properties.
Serializable types
Unity can serialize fields of the following types:
- All classes inheriting from UnityEngine.Object, for example GameObject, Component, MonoBehaviour, Texture2D, AnimationClip.
- All basic data types, such as int, string, float, bool.
- Some built-in types, such as Vector2, Vector3, Vector4, Quaternion, Matrix4x4, Color, Rect, LayerMask.
- Arrays of a serializable type
- Lists of a serializable type
- Enums
- Structs
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.
Лайфхаки редактора Unity 3D. Часть 1: Атрибуты
Здравствуйте, друзья! Заметил, что многие программисты пропускают богатые возможности Unity кастомизации редакторского интерфейса по тем или иным причинам. В этом цикле статей я распишу несколько совсем простых примеров, позволяющих облегчить жизнь геймдизайнерам и художникам, а также парочку примеров посложнее, но также легко реализуемых.
Большая часть взята из опыта использования, куда попала из родной документации движка. Вы легко можете сами найти необходимую информацию, поворошив документацию Unity 3D. Просто, по собственному опыту скажу, что у многих программистов либо нет времени, либо нет желания копаться в мантрах. Поэтому и выкладываю максимально краткое руководство по основным редакторским возможностям, которые я использовал на работе и в своих проектах.
Встроенные атрибуты
Я не буду расписывать все атрибуты, распишу лишь кратко те, которыми самому приходилось пользоваться.
Атрибуты к методам
Позволяет создать меню для доступа к статическому методу. Через “/” указывается иерархия. Можно располагать новые кнопки в стандартном главном меню движка, указывая путь, например “File/Create New Asset”.
Всего может содержать три параметра.
Также, если использовать элементы главного меню, то дополнительная кнопка будет появляться не только там, но и в контекстном меню на правую кнопку мыши. Например, в своем проекте, я добавил копирование пути к ассету.
Кроме того, на методы можно назначить горячие клавиши. Для этого, прямо в пути к меню нужно написать необходимую комбинацию. Для этого нужно использовать один из служебных символов+буква.
% — ctrl в Windows или cmd в OSX
# — shift
& — alt
В моем проекте, с копированием пути к ассету это выглядит так
Атрибуты к переменным
Можно сказать, это кастомный редактор для атрибута, который позволяет задать границы задаваемого значения через инспектор. Не клампит в реалтайме — только в инспекторе. Полезно, если задаете, например, вероятность выпадения предметов от 0 до 1 или от 0 до 100.
Задает подпись над сериализуемым полем, которая отображается в инспекторе.
Задает отступ в инспекторе.
Задает подсказку в инспекторе при наведении на сериализуемую переменную.
Позволяет сериализовать переменные вне зависимости от их области видимости. Очень полезный атрибут, который позволяет сделать все переменные класса приватными, но настраиваемыми в инспекторе.
Позволяет убирать сериализацию у паблик переменных. Очень не рекомендую данных подход. Уж лучше определить свойство get;set; и получать данные по нему. Кроме того, свойство можно сделать виртуальным и перегрузить, при необходимости, в классах наследниках. А тот факт, что оно публичное, позволяет использовать его в интерфейсах.
Позволяет скрыть сериализуемое поле в инспекторе. Неважно, будет оно публичным или приватным/протектным с атрибутом SerializeField.
Атрибуты к классам
ScriptableObject — очень полезный класс, который позволяет хранить условную базу данных в проекте, не прибегая к префабам. В проекте создаются объекты с созданным вами типом. Можно работать также, как с префабами, имеют свои преимущества и недостатки. Вообще, этот класс — тема для отдельной статьи, небольшой, но информативной.
Указанный выше атрибут позволяет создать в проекте объект с вашим типом, по тому пути, где вы открыли контекстное меню.
Позволяет работать скрипту в редакторе. В основном, полезно для постэффектов, поскольку позволяет сразу оценить результат в камере без запуска проекта. Но иногда можно использовать и для других целей.
Например, в качестве инициализатора сериализуемых полей встроенных типов, типа transform, renderer, rectTranform и т.п. Не рекомендовал бы повсеместно, лучше требовать ручной инициализации, либо написать редакторский скрипт, но иногда удобно.
Необходимость существования другого компонента
Unity — Scripting API: RequireComponent
Заставляет редактор требовать наличие определенного компонента на том же объекте, на котором висит скрипт с данным атрибутом. При добавлении сразу создает на том же объекте компонент указанного типа. Также запрещает удалять уже добавленный компонент.
Новый элемент в меню добавления компонента
Unity — Scripting API: AddComponentMenu
Добавляет подменю в выпадающий список в меню Components →… и AddComponent. Удобно, если у вас большая библиотека кода и нужно организовать её в редакторе.
На этом, простая часть заканчивается и добавлю совсем немного в меру сложной.
Кастомные атрибуты (CustomPropertyDrawer)
Unity — Scripting API: PropertyAttribute
Unity — Scripting API: PropertyDrawer
Если вам недостаточно атрибутов приведенных выше, вы всегда можете воспользоваться API для написания собственных настраиваемых атрибутов. Реализация данного инструмента также достаточно проста и заключается в нескольких шагах. В данном примере, я опишу создание
собственного атрибута к переменной.
Во-первых, нужно определить класс-наследник от стандартного класса PropertyAttribute. Я сразу создам его с конструктором, в котором входящим параметром будет путь к списку того, что нам нужно использовать в атрибуте.
Во-вторых, после этого создаем скрипт редактора, в котором будем рисовать этот самый новый класс. Его нужно унаследовать от PropertyDrawer, а также написать к нему атрибут CustomPropertyDrawer.
Я называю классы наиболее общими наименованиями, дабы просто показать принцип использования настраиваемых.
База готова, теперь нам нужно нарисовать данный атрибут в том виде, в котором он нам нужен. В основном, атрибуты я использую в тех случаях, когда возможностей перечисления (enum) недостаточно, но нужно отрисовать выпадающий список с выбором.
Например, у вас есть база эффектов, у которой есть соответствие id → эффект. Вы храните где-то эту базу, неважно в ScriptableObject’e или на каком-то префабе. Вот простейшая реализация “хранилища”
Примечание — всегда создавайте в классах первое сериализуемое поле строковым. Из-за этого в списках элементы будут именоваться не как element 1, element 2. а таким образом, каким вы назначите переменную в инспекторе.
Для классов, с которыми я взаимодействую “извне”, я всегда пишу интерфейс. У каждого свой подход к этому моменту, но данный подход легко позволит, в случае чего, подменить класс только в одном месте на другой, а остальные так и будут работать с интерфейсом. Тем более, юнити поддерживает работу с интерфейсами в таких методах, как GetComponent(s)…, GetComponent(s)InChildren и т.п.
Интерфейс и класс эффекта
Интерфейс и класс контейнера
Обычно, объекты с такими данными я располагаю в ресурсах, потом беру оттуда. Можно расположить и просто в проекте и где необходимо определить ссылки. Но я иду по более простому и уже проверенному на не одной платформе пути.
Редактор
Осталось дописать редактор:
Заключение
Все приведенные выше «лайфхаки» могут упростить не только вашу работу (особенно когда проект разрабатывается несколько месяцев или лет), но и работу новичков, а также художников и геймдизайнеров. Не каждый специалист полезет в код. Конечно, хорошая организация и дисциплина может помочь и так документировать каждый компонент, но не всегда это получается, особенно у независимых разработчиков.
P.S.: Позже, напишу еще пару статей по другим типам апгрейдов редактора, в которые включу:
CustomEditor;
CustomPropertyDrawer;
EditorWindow;
Класс Debug и как его едят;
Класс Gizmos.
А также дополню примеры окном и пользовательским редактором. Пишите в комментариях, нужны ли подобные статьи или можно обойтись тем, что уже есть на Хабре.
Why should I use SerializeField?
I have just started to learn C# and Unity, and there is one thing that I can not get used to:
Why and when should I use [SerializeField] ?
Is it bad to leave variables hard coded despite using [SerializeField] and have more text boxes in my unity interface?
2 Answers 2
Why and when should I use [SerializeField]?
Using the SerializeField attribute causes Unity to serialize any private variable. This doesn’t apply to static variables and properties in C#.
You use the SerializeField attribute when you need your variable to be private but also want it to show up in the Editor.
For example, this wouldn’t show up in the Editor:
And this is because it’s a private variable but the one below should show up in the Editor:
That’s because you applied SerializeField to it and you’re telling Unity to serialize it and show it in the Editor.
Note that private variables has more to do with C# than Unity. There is also public variable variables. Marking your variable private means that you don’t want another script to be able to access that variable. There is also public qualifier. Marking your variable public means that you want your other scripts to be able to access that variable.
Sometimes, you want other scripts to be able to access your variable from another script but you don’t want the public variable to show up in the Editor. You can hide the public variable with the [HideInInspector] attribute.
This will show in the Editor:
This will not show in the Editor:
Is it bad to leave variables hard coded despite using [SerializeField] and have more text boxes in my unity interface?
Yes, it’s mostly bad especially for new users. It shouldn’t be a big deal for a long time Unity and C# programmer. The reason this is bad is because when you have the code below:
The default value is 5 in the Editor. Once you save the script this variable is now updated in the Editor as 5. The problem is that you can change this from the Editor to 14 . Once you change it from the Editor, the value in the script will still be 5 but when you run it, Unity will use the value you set in the Editor which is 14 . This can cause you so much time troubleshooting something that isn’t even a problem just because there is a different value being used that is set in the Editor while you’re expecting the default value set in the script to be used.
The only way for for the score variable to reset back to it’s default 5 variable is when you either rename the variable to something else or reset it from the Editor. It won’t even change even when you change the value from 5 to 3 from the script. It has to be renamed or reset from the Editor. It’s worth knowing but when you get used to Unity, you won’t have to worry about this.