Управление сложными сборными иерархиями в Unity3D

Я задавал этот вопрос в нескольких местах, и до сих пор не понял его полностью, поэтому, возможно, некоторые умные люди здесь поймут, как к этому подойти.

Каков наилучший способ поддержания глубоко вложенной иерархии префабов в проекте? Скажем, у нас есть несколько экранов с графическим интерфейсом, сделанные из более мелких, общих компонентов. Для простоты давайте назовем первые "представления", а вторые - "компоненты". Представления имеют дело с семантикой (например, представление инвентаря, представление магазина); компоненты настраиваются, но к ним вообще не прикрепляется бизнес-логика (например, кнопка заботится только о своем обратном вызове / обработчике события OnTap).

Оба представления и компоненты могут быть вложенными.

Представления GUI должны быть повторно использованы в нескольких сценах.

Основная проблема этого подхода в Unity заключается в том, что любая вложенная иерархия, однажды превращенная в префаб, теряет ссылки на свои дочерние префабы, как в этом (полностью составленном, но все еще действительном) примере:

- storeView - UIViewHeader - UIHeaderLabel<Text> - UIList - UIListItem - UIThumbnail - UITitleLabel<Text> - UISubTitleLabel<Text> - UIPrimaryButton<Button> - ...

Я хотел бы сохранить все эти небольшие компоненты пользовательского интерфейса * в отдельных префабах, но также сохранить префаб storeView, чтобы я мог легко добавить его в разные сцены. К сожалению, как только мы создаем prefab storeView, все ссылки prefab UI* теряются. Учитывая это, мы могли бы попробовать другой подход, в котором вместо того, чтобы иметь prefab storeView с контентом, мы оставляем его пустым и выбираем один из следующих вариантов:

  1. прикрепить поведение к storeView и загрузить дочерние префабы во время выполнения
    • минусы: усложняет рабочий процесс дизайнера, вносит сложность в сценарий, что может быть более подвержено ошибкам с точки зрения разработчика
    • Плюсы: упрощает повторное использование storeView между сценами, готовые компоненты могут быть стилизованы, изменены глобально
  2. сохранить storeView как пустой сборный домик и собирать его в каждой сцене, где это требуется
    • минусы: компоненты должны быть подключены вручную, все еще легко сохранить весь storeView случайно и потерять предварительно подготовленные ссылки
    • Плюсы: гарантирует, что префаб ссылки на компоненты поддерживаются, допускает небольшие различия между представлениями (imho, это проблема на самом деле, так как они должны принадлежать слою конфигурации)
  3. сохранить весь магазин Посмотреть как сборный
    • минусы: ужасно масштабируется, делает итерации по новым функциям или небольшим изменениям UX более трудоемким (дополнительное тестирование, приемочные тесты и т. д.)
    • плюсы: это быстрое и грязное решение, которое хорошо работает с небольшими проектами
  4. использовать Prefab Evolution или аналогичный
    • минусы: я предполагаю, что пакет будет считаться устаревшим с помощью Nested Prefabs, которые включены в план? Требуется в зависимости от стороннего кода и может быть недостаточно гибким (какие-либо мнения здесь, ребята?)
    • Плюсы: Из многих (смешанных) отзывов, которые я видел, некоторые были довольно позитивными. Однако чем сложнее становится проект, тем менее позитивны эти отзывы.
  5. написать кучу пользовательских скриптов редактора:
    • минусы: также отнимает много времени - похоже на то, что должно быть обеспечено платформой, даже если она имеет дело в основном с играми
    • Плюсы: полный контроль над поведением, могут быть улучшены разработчиками с обратной связью дизайнеров. Кто-то может возразить, что наличие дисциплины в отношении наличия средств реализации, тестирования и удобных для разработчиков инструментов в качестве требований к функциональности звучит как хорошая практика проектирования (что приводит к уменьшению технического долга и упрощению обслуживания)

Вот мое личное, 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();,

Не универсальный / масштабируемый материал, но, по крайней мере, у вас есть что-то легкое / удобное в обслуживании, пока они не развернут вложенные префабы ( временная шкала, как говорится, неопределенная).

Другие вопросы по тегам