Управление сложными сборными иерархиями в Unity3D
Я задавал этот вопрос в нескольких местах, и до сих пор не понял его полностью, поэтому, возможно, некоторые умные люди здесь поймут, как к этому подойти.
Каков наилучший способ поддержания глубоко вложенной иерархии префабов в проекте? Скажем, у нас есть несколько экранов с графическим интерфейсом, сделанные из более мелких, общих компонентов. Для простоты давайте назовем первые "представления", а вторые - "компоненты". Представления имеют дело с семантикой (например, представление инвентаря, представление магазина); компоненты настраиваются, но к ним вообще не прикрепляется бизнес-логика (например, кнопка заботится только о своем обратном вызове / обработчике события OnTap).
Оба представления и компоненты могут быть вложенными.
Представления GUI должны быть повторно использованы в нескольких сценах.
Основная проблема этого подхода в Unity заключается в том, что любая вложенная иерархия, однажды превращенная в префаб, теряет ссылки на свои дочерние префабы, как в этом (полностью составленном, но все еще действительном) примере:
- storeView
- UIViewHeader
- UIHeaderLabel<Text>
- UIList
- UIListItem
- UIThumbnail
- UITitleLabel<Text>
- UISubTitleLabel<Text>
- UIPrimaryButton<Button>
- ...
Я хотел бы сохранить все эти небольшие компоненты пользовательского интерфейса * в отдельных префабах, но также сохранить префаб storeView, чтобы я мог легко добавить его в разные сцены. К сожалению, как только мы создаем prefab storeView, все ссылки prefab UI* теряются. Учитывая это, мы могли бы попробовать другой подход, в котором вместо того, чтобы иметь prefab storeView с контентом, мы оставляем его пустым и выбираем один из следующих вариантов:
- прикрепить поведение к storeView и загрузить дочерние префабы во время выполнения
- минусы: усложняет рабочий процесс дизайнера, вносит сложность в сценарий, что может быть более подвержено ошибкам с точки зрения разработчика
- Плюсы: упрощает повторное использование storeView между сценами, готовые компоненты могут быть стилизованы, изменены глобально
- сохранить storeView как пустой сборный домик и собирать его в каждой сцене, где это требуется
- минусы: компоненты должны быть подключены вручную, все еще легко сохранить весь storeView случайно и потерять предварительно подготовленные ссылки
- Плюсы: гарантирует, что префаб ссылки на компоненты поддерживаются, допускает небольшие различия между представлениями (imho, это проблема на самом деле, так как они должны принадлежать слою конфигурации)
- сохранить весь магазин Посмотреть как сборный
- минусы: ужасно масштабируется, делает итерации по новым функциям или небольшим изменениям UX более трудоемким (дополнительное тестирование, приемочные тесты и т. д.)
- плюсы: это быстрое и грязное решение, которое хорошо работает с небольшими проектами
- использовать Prefab Evolution или аналогичный
- минусы: я предполагаю, что пакет будет считаться устаревшим с помощью Nested Prefabs, которые включены в план? Требуется в зависимости от стороннего кода и может быть недостаточно гибким (какие-либо мнения здесь, ребята?)
- Плюсы: Из многих (смешанных) отзывов, которые я видел, некоторые были довольно позитивными. Однако чем сложнее становится проект, тем менее позитивны эти отзывы.
- написать кучу пользовательских скриптов редактора:
- минусы: также отнимает много времени - похоже на то, что должно быть обеспечено платформой, даже если она имеет дело в основном с играми
- Плюсы: полный контроль над поведением, могут быть улучшены разработчиками с обратной связью дизайнеров. Кто-то может возразить, что наличие дисциплины в отношении наличия средств реализации, тестирования и удобных для разработчиков инструментов в качестве требований к функциональности звучит как хорошая практика проектирования (что приводит к уменьшению технического долга и упрощению обслуживания)
Вот мое личное, v. Идеалистическое, нереалистичное решение этого *:
Используйте компонентную архитектуру, в которой дочерние префаб-ссылки по умолчанию хранятся в сложных префабах. Внутренне представьте их как UIView и подпредставления для мобильных устройств (Какао) или классы компонентов в React или, что лучше, функциональные компоненты - React/Cycle/Elm/ все, что хорошо сочетается с FRP (да, я знаю, что эти подходы отличаются во многих отношениях, но ключ - это сочетаемость, достигаемая либо функциональной композицией, декораторами и так далее, и так далее...).
- минусы: я предполагаю, что мои трудности здесь происходят из-за отсутствия у меня опыта работы с Unity, и есть более очевидное, возможно, идиоматическое решение (которое я любезно прошу:))
плюсы: упрощает тестирование и итерацию новых функций, делает префабы более мощными, не теряя при этом ни одного из их преимуществ (исправьте меня, если я ошибаюсь, я все еще знакомлюсь с Unity)
пожалуйста, не думайте, что я ожидаю всего этого от Unity, но это одно из возможных направлений, даже если 1% от этого соответствует действительности.
Просто чтобы прояснить, это не ругательство в отношении Unity, так как разработчик, ранее работавший с мобильным (нативным) и веб-интерфейсом, я нахожу впечатляющим, как много моих проблем он решает, и как смехотворно просты некоторые из этих решений.
1 ответ
Я бы, вероятно, сохранил составные виды в отдельных сценах. Просто рассмотрите эти сцены как сборные, содержащие только один объект-прототип данного класса.
С помощью SceneManager.LoadScene
с LoadSceneMode.Additive
Вы могли бы даже создать некоторый статический фабричный метод, такой как:
public class UIStoreView
{
public static UIStoreView Instance()
{
SceneManager.LoadScene("UIStoreView", LoadSceneMode.Additive);
return GameObject.Find("UIStoreView");
}
}
С некоторой конвекцией имен вы можете достичь чего-то простого storeView = UIStoreView.Instance();
,
Не универсальный / масштабируемый материал, но, по крайней мере, у вас есть что-то легкое / удобное в обслуживании, пока они не развернут вложенные префабы ( временная шкала, как говорится, неопределенная).