|
|
||||||||||||||||
[Unity, лайфхак] Как сделать адекватный синглтон (singleton или уникальный для сцены) компонент05.03.2017, 20:27. Показов 10076. Ответов 13
Метки нет (Все метки)
Что такое singleton – я надеюсь знают все.
Какие цели лично я преследую при использовании синглтона? Во-первых – легкий доступ к экземпляру класса в коде любого компонента. Во-вторых – запрет на добавление нескольких компонентов в сцену, если по логике этот компонент должен быть уникальным (настройки, BestScore…..). Причем запрет должен действовать и на уровне редактора, и на уровне кода. В-третьих – все должно быть понятно, поведение компонента естественно и ожидаемо, логика синглтона не должна мешать нормальной работе компонента и не должна сказываться на производительности готового приложения. В интернете достаточно много примеров по реализации синглтона на Unity. С ленивой инициализацией, с инициализацией в Awake или Reset, с кэшированием ссылок и т.д. и т.п. Приведу пример своего компонента: Код на С#
Все это, конечно, прекрасно. И пока не сильно отличается от того, что можно найти на первой странице гугла по запросу «синглтон в юнити». Но я не увидел, чтобы авторы статей рассматривали 2 проблемы, с которыми столкнулся я: 1) При пересборке проекта (читай – при ЛЮБОМ изменении в любой части кода) коллекция _instances отчищается, т.к. класс UniqueComponentAtScene не является сериализуемым. А быть он таким не может, потому что нам заранее неизвестно, насколько сложные будут наследующие классы. Возможно их нельзя будет сделать сериализуемыми в принципе. И «ближайший» вызов метода Awake, где _instances заполняется, произойдет только в случае запуска проекта в редакторе. Т.е. поведение компонента UniqueComponentAtScene – НЕ ОЖИДАЕМО, и заставляет каждый раз жмакать кнопку Play в редакторе. Можно забыть про это и словить внезапную ошибку NullReferenceException. 2) Если наследующий UniqueComponentAtScene класс1 будет иметь атрибут RequireComponent с указанием на класс2, который тоже является наследником UniqueComponentAtScene – то произойдет ошибка при добавлении дубля компонента класса1 на сцену.
Ну и после такого долгого введения перейдем непосредственно к лайфхаку Для решения первой проблемы я использую такой хитрый атрибут, как DidReloadScripts. Упоминаний про него я нигде не встречал и вообще наткнулся совершенно случайно. Он позволяет пометить статичный метод, который будет вызван в редакторе после пересборки проекта или при первой загрузке редактора. После этого нам надо найти всех наследников UniqueComponentAtScene с помощью рефлексии и найти экземпляры этих классов на сцене. Когда все экземпляры, или компоненты, или синглтоны, найдены – вызываем для них Awake.Правда здесь тоже есть нюанс – почему-то метод, расположенный в абстрактном генерик классе и помеченный атрибутом DidReloadScripts, вызывает ошибку "TypeLoadException: A type load exception has occurred". Толи баг, толи моих знаний языка не хватает для понимания… В общем, необходимо добавить прямо в файл с кодом UniqueComponentAtScene скриптуемый объект, в котором уже прописать нужный метод с атрибутом DidReloadScripts. Т.е. полный код файла UniqueComponentAtScene.cs будет выглядеть так: Полный код примера на С#
Со второй проблемой способа борьбы я не придумал. Разве только словесно запретить использовать RequireComponent с указанием на наследников UniqueComponentAtScene Если вы знаете, что делать со второй проблемой – с радостью выслушаю ваше решение. Ну и вообще замечания, предложения, пожелания приветствуются! _______________________________________ site: ocp.onl e-mail: hello@ocp.onl
0
|
||||||||||||||||
| 05.03.2017, 20:27 | |
|
Ответы с готовыми решениями:
13
Unity 2d как рандомно загружать заготовленные сцены |
|
753 / 600 / 204
Регистрация: 06.08.2015
Сообщений: 2,432
|
|
| 05.03.2017, 20:57 | |
|
А для чего такие сложности? Массивы синглтонов + наследование от синглтонов? Зачем?
0
|
|
|
|
|
| 05.03.2017, 21:48 [ТС] | |
|
Ну есть несколько причин:
1) Чтобы отделить мух от котлет. Механизм синглтонов отдельно, механизм игровой логики отдельно Вся их связь в одной строчке - base.Awake в наследнике.2) Для уменьшения повторяемости кода. Если несколько синглтонов - то для каждого придется писать заново обработку. А т.к. в Unity конструкторы классов, наследных от MonoBehaviour, недоступны - то придется все запихивать в Awake. И читаемость это не улучшит. 3) По наследованию от UniqueComponentAtScene можно понимать, что компонент должен быть уникальным. С другой стороны, если просто дописывать св-во Instance в каждый такой класс - это будет совсем не наглядно. А как вы используете синглтоны в юнити? Может покажете пример?
0
|
|
|
753 / 600 / 204
Регистрация: 06.08.2015
Сообщений: 2,432
|
|||||||||
| 05.03.2017, 22:25 | |||||||||
|
Вот так, например, можно, чтобы не искать компонент везде, где нужна локализация:
0
|
|||||||||
|
|
||||||||
| 05.03.2017, 23:22 [ТС] | ||||||||
![]() Я это и делалВы привели пример с менеджером локализации. Хорошо, давайте разберемся. 1) Если вам еще нужно сделать менеджер ввода, менеджер настроек уровня, еще три менеджера и четыре других каких-то уникальных компонента? В каждый вы будете дописывать
2) Смотрим дальше. Например, нерадивый геймдизайнер случайно добавил на сцену три менеджера локализации и забыл про это. Позже, потратив на настройку одного из них много-много времени - он решил проверить результат. И запустил сцену. И вот тут совсем не обязательно, что глупый Юнити не удалит настроенный компонент, оставив пустой в качестве синглтона. Соответственно надо пометить компонент ExecuteInEditMode, и запоминать, какой из компонентов добавлен первым (_isFirst). Чтобы удалять остальные, но не трогать его. Посмотрите, пожалуйста, какие цели были поставлены - запретить повторное добавление компонента в сцену, если такой уже есть. Стандартная реализация из гугла этому не препятствует.
0
|
||||||||
|
295 / 244 / 128
Регистрация: 24.12.2014
Сообщений: 708
|
|||||||||||||
| 06.03.2017, 03:58 | |||||||||||||
Правда не знаю как будет вести себя производительность, возможно приложение будет дольше грузится или выбрасывать исключения, поскольку Unity не всегда дружит со статическими конструкторами, которые работают с компонентами юнити. Но с файлами проблем не возникало. Если я ошибаюсь, то напишите каким вы видите процесс доступа к синглтонам. Судя по вашим идеям вы ходите сделать что-то типа менеджера синглтонов Чтобы было примерно так:МЕНЕДЖЕР.[ТИП_ИЛИ_НАЗВАНИЕ_КОНКРЕТНОГО_СИНГЛОНА].[ВОЗМОЖНО_ЕЩЁ_INSTANCE].МЕТОД_СИНГЛОТА или для примера Setting<Localization>.Instance.SetLang( "ru" ); Неужели такой вид будет легче читать и писать, чем например этот: Localization.SetLang( "ru" ); Учитывая, что вы хотите ещё сделать какое-то наследование, то скорее всего "Чтобы отделить мух от котлет" превратится в кашу, причём густую Пусть будет несколько менеджеров, но ими будет легче управлять и риск наткнуться на NullReferenceException будет минимальным.
0
|
|||||||||||||
|
753 / 600 / 204
Регистрация: 06.08.2015
Сообщений: 2,432
|
|||
| 06.03.2017, 07:52 | |||
|
0
|
|||
|
|
||||||
| 06.03.2017, 13:30 [ТС] | ||||||
![]() Просто доступ идет через [ClassName].Instance.[fieldOrPropertyOrMethod]Менеджера, как такового нет. Добавлено через 3 часа 16 минут Ну при большом желании можно развернуть в более классический код. Да и к тому же все мы люди. Человеческий фактор - самый непредсказуемый.А в общем то вы согласны, что ТАКАЯ проблемная ситуация может произойти?
0
|
||||||
|
753 / 600 / 204
Регистрация: 06.08.2015
Сообщений: 2,432
|
|||||||||||||
| 06.03.2017, 21:25 | |||||||||||||
|
Вот этот код
Нет, Linq допустим только в методах НЕ КАЖДЫЙ кадр, а в идеале только там, где без него вообще никак.
0
|
|||||||||||||
|
|
|||||||||||||
| 06.03.2017, 22:48 [ТС] | |||||||||||||
Да и вообще, скороcть работы linq - это тема для холивара. Бессмысленно это обсуждать.
0
|
|||||||||||||
|
295 / 244 / 128
Регистрация: 24.12.2014
Сообщений: 708
|
|||||||||||||||||||
| 07.03.2017, 17:47 | |||||||||||||||||||
Ключи в словарях должны быть всегда уникальными, по-этому это можно использовать для того, чтобы контролировать уникальность. При запуске приложения можно легко отловить место, где происходит добавление дубликата. Но так как ваша цель сделать это на уровне редактора, то вряд ли эта цель достижима, разве что через какие-то костыли )
0
|
|||||||||||||||||||
|
753 / 600 / 204
Регистрация: 06.08.2015
Сообщений: 2,432
|
||
| 07.03.2017, 22:49 | ||
|
0
|
||
|
|
|||
| 10.03.2017, 01:01 [ТС] | |||
|
Ну есть Unity wiki. Какой никакой, а источник стандартизации информации, пускай и сообществом. http://wiki.unity3d.com/index.php/Singleton
![]() Вообще я согласен, раз это игра - за оптимизацией надо следить. Все-таки (n) раз в секунду метод вызывается. Использовать массивы вместо листов, for вместо foreach, кэшировать ссылки вместо FindObject и т.д. и т.п. Это все скорее монотонный труд и дело привычки. Т.е. никак не относится к подобной, как я понял, нестандартной задаче
0
|
|||
|
295 / 244 / 128
Регистрация: 24.12.2014
Сообщений: 708
|
|||
| 10.03.2017, 02:20 | |||
|
0
|
|||
| 10.03.2017, 02:20 | |
|
Помогаю со студенческими работами здесь
14
Компонент для создания двухмерной сцены Как записать звук со сцены в Unity, а затем сохранить его на рабочий стол? Unity сцены. Unity lifecycle
Как сделать уникальный личный кабинет, авторизацию и баланс для каждого пользователя? Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
|||
|
Отчёт о спецтехнике находящейся в ремонте
Maks 20.04.2026
Отчёт из решения ниже размещен в конфигурации КА2.
Задача: отобразить спецтехнику, которая на данный момент находится в ремонте.
Есть нетиповой документ "Заявка на ремонт спецтехники" который. . .
|
Памятка для бота и "визитка" для читателей "Semantic Universe Layer (Слой семантической вселенной)"
Hrethgir 19.04.2026
Сгенерировано для краткого описания по случаю сборки и компиляции скелета серверного приложения. И пусть после этого скажут, что статьи сгенерированные AI - туфта и не интересно. И это не реклама -. . .
|
Запрет удаления строк ТЧ документа при определенном условии
Maks 19.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "Аккумуляторы", разработанного в конфигурации КА2. У данного документа есть ТЧ, в которой в зависимости от прав доступа. . .
|
Модель заражения группы наркоманов
alhaos 17.04.2026
Условия задачи сформулированы тут
Суть:
- Группа наркоманов из 10 человек.
- Только один инфицирован ВИЧ.
- Колются одной иглой.
- Колются раз в день.
- Колются последовательно через. . .
|
|
Мысли в слух. Про "навсегда".
kumehtar 16.04.2026
Подумалось тут, что наверное очень глупо использовать во всяких своих установках понятие "навсегда". Это очень сильное понятие, и я только начинаю понимать край его смысла, не смотря на то что давно. . .
|
My Business CRM
MaGz GoLd 16.04.2026
Всем привет, недавно возникла потребность создать CRM, для личных нужд. Собственно программа предоставляет из себя базу данных клиентов, в которой можно фиксировать звонки, стадии сделки, а также. . .
|
Знаешь почему 90% людей редко бывают счастливыми?
kumehtar 14.04.2026
Потому что они ждут. Ждут выходных, ждут отпуска, ждут удачного момента. . .
а удачный момент так и не приходит.
|
Фиксация колонок в отчете СКД
Maks 14.04.2026
Фиксация колонок в СКД отчета типа Таблица.
Задача: зафиксировать три левых колонки в отчете.
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
/ / . . .
|