Паттерн Единая Точка Входа (или Entry Point). Как использовать в Unity?

Sdílet
Vložit
  • čas přidán 7. 07. 2024
  • Поддержать канал:
    www.donationalerts.com/r/game...
    paypal.me/gamedevlavka
    Коротенькое 🤡 видео с одним из самых важных на мой взгляд паттернов проектирования игр на Unity. Почему-то о нем мало кто говорит, по крайней мере мне он достаточно долго не попадался на глаза, тем не менее, единая точка входа используется повсеместно. Поэтому я решил, что не рассказать о данном паттерне было бы преступлением со стороны Лавки Разработчика.
    Смотрим, комментируем, ставим лайки, подписываемся на канал!
    ___
    Лавка Разработчика в других соц. сетях, добавляйтесь!
    t.me/gamedevlavka - телеграм канал Лавки Разработчика
    t.me/gamedevtavern - ламповый чат
    / discord - дискорд
    gamedevlavka - вконтактик
    __________
    0:00 Вступление
    0:30 Рассказываю подробности примера
    1:27 Собственно, рассказ о паттерне Единая Точка Входа

Komentáře • 75

  • @forcesoftheevil9252
    @forcesoftheevil9252 Před rokem +15

    Спасибо за видео! Хоть некоторые коментаторы пишут, что эта тема ну у ж очень очевидная, но не стоит забывать, что на ютубе много туторов без архитектуры. Просто сплошные монобехи. Хочу увидеть ещё урок по архитектурным паттернам.

  • @qiweivaneevmaksim9074
    @qiweivaneevmaksim9074 Před 5 měsíci +1

    Ничего себе как быстро и по теме, побольше бы таких

  • @gamedevGod
    @gamedevGod Před rokem +1

    Отличное видео! Спасибо😉

  • @syntez4966
    @syntez4966 Před rokem +1

    огромное спасибо! всё понятно, шикардос

  • @antigames4656
    @antigames4656 Před rokem

    О вот этот видосик я ждал 😊

  • @skadexgd5057
    @skadexgd5057 Před rokem +1

    Спасибо за видео!

  • @RimuruDev
    @RimuruDev Před rokem +13

    На Unity использую Composition Root + Zenject для реализации Entry Point. Очень удобно для резолва сервисов и статичных данных. Но видео интересное, поделюсь им со знакомыми. Благодарю за труды❤

    • @anton3757
      @anton3757 Před rokem +1

      База

    • @gamedevlavka
      @gamedevlavka  Před rokem +1

      Да, так часто делается :)

    • @YasnaKo
      @YasnaKo Před rokem +3

      Посоветуете гайд для чайника? С Zenject шапочно знакома, про Composition Root впервые слышу

    • @maksimsazanovich6087
      @maksimsazanovich6087 Před 11 měsíci +1

      о, и ты тут) какой же маленький мир

  • @nepochat
    @nepochat Před rokem

    Спасибо, все понятно)

  • @user-ux2gs4qf5w
    @user-ux2gs4qf5w Před rokem

    Полезные знания, спасибо

  • @YasnaKo
    @YasnaKo Před rokem +7

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

    • @gamedevlavka
      @gamedevlavka  Před rokem +2

      Подумаю, как можно об этом рассказать. И нет, я в видео опомянул, что точка входа - это место разворачивается приложения или модуля. Сцена в данном примере является отдельным таким модулем

    • @YasnaKo
      @YasnaKo Před rokem

      @@gamedevlavka спасибо!

  • @user-mm7ch3xw4e
    @user-mm7ch3xw4e Před rokem +1

    Пока вкуриваем 5 видео про архитектуру, после будем паттерны смотреть)

  • @andrewalexart
    @andrewalexart Před 11 měsíci

    Спасибо за урок!
    Как потом между сценами эти данные перенести? после выгрузки бутстрапа все ссылки потеряются

  • @Anton-ny6tx
    @Anton-ny6tx Před rokem +3

    Немного не понял, про фейковые сервисы. Тот же Zenject или VContainer строит граф зависимостей. Чтобы прокинуть сервис в стартер, нужно и сам стартер прокинуть в DI. Ошибки же будут сыпаться при первой возможности, мол не смог зарезолвить, тк. нет такого типа в контейнере, тк. запуск не с бутстрапа был.

    • @gamedevlavka
      @gamedevlavka  Před rokem

      Тут моя ошибка, я не проговорил, что феейковые сервисы - исключительно для тестов в редакторе. Чтобы не запускать и не проходить несколько сцен до текущей. При этом некоторые сервисы требуют наличие ссылок на Project сервисы, в этом случае (в редакторе, лучше используя дефайны) можно создать фейковые сервисы, чтобы сцена работала

  • @servalstar
    @servalstar Před rokem +2

    По моему, Entry Point это не паттерн, а основа любой архитектуры.

    • @gamedevlavka
      @gamedevlavka  Před rokem +1

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

  • @n0ra754
    @n0ra754 Před rokem +3

    Просьба сделать видео о сохранении в проекте в целом. Все рассказывают о том как сохранить в файл, но не говорят о системе сохранений в игре в целом. Например нужно сохранять всю игру целиком в реалтайме (например майнкрафт). Как лучше подобное реализовать? Также интересно будет посмотреть о передаче данных между сценами (например 1 сцена на все уровни и данные передаются из меню).

    • @gamedevlavka
      @gamedevlavka  Před rokem +1

      Понимаю запрос, это не одним видео делается, чтобы понятно было. Ну либо одним, но длинным)
      Сделаю, как нибудь, там очень много нюансов)

    • @n0ra754
      @n0ra754 Před rokem

      @@gamedevlavka Спасибо

    • @Hatemsla
      @Hatemsla Před rokem +2

      Зачем тебе сохранение в реалтайме? Это в любом случае будет очень медленно, делать сохранение каждую секунду. Чтобы сохранять сцену есть различные способы, все зависит от того что ты хочешь сохранить, данные пользователя? PlayerPrefs. Состояние сцены? Будь добр напиши свой парсер сцены, который будет парсить объекты твоей сцены в файл, будь то json или xml, да хоть обычный txt. Как парсить сцену? Определиться с данными, которые ты хочешь сохранять, по сути минимум это позиция, вращение и размер, а дальше уже пожеланию. Для лучшей загрузки всего этого используешь addressables, это позволит относительно быстро загружать сохраненную сцену, в том числе и в билде.
      Чтобы передавать данные между сценами существуют такие вещи как static переменные, DonDestroyOnLoad, Локальное сохранение данных в файл или PlayerPrefs

    • @gamedevlavka
      @gamedevlavka  Před rokem +1

      ​@@Hatemsla многое сказано, с частью я согласен, с частью - есть нюансы. Вообще весь ответ на вопрос можно свести к тому: а чего хочется? Сохранение бывает по сейвпоинтам (сохраняется не каждый объект на сцене, как в метроидваниях, например), по уровням (тут вообще мало инфы хранится), открытый мир (тот случай с сохранением сцены), сохранение в облако, хранение и сохранение прямо на сервере (майнкрафт), сохранение в в один файл, в множество файлов, в префсы, в общем вариантов целая куча, и самый главный вопрос тут - какой нужен для конкретного проекта.
      Передавать данные между сценами нужно через архитектурные решения, так правильнее сказать. А какие - это уже тоже очень емкий вопрос. Думаю, подниму его на курсе, который делаю. И когда-нибудь он будет готов, но не сегодня :)

    • @Hatemsla
      @Hatemsla Před rokem

      @@gamedevlavka В целом да, вообще сохранение чего либо в игре это концептуальный вопрос и он зависит от многого, банально, если игра сетевая то принципы сохранения и хранения данных будет разительно(или нет) отличаться от сингл решения. Способов, подходов и решений много, я лишь перечисли то, что так или иначе придется использовать, если нужна система сохранения

  • @KitGorn
    @KitGorn Před rokem +1

    Start можно запускать как корутину? Ты открыл мне новый мир)

    • @erickmanciny1352
      @erickmanciny1352 Před 9 měsíci

      Его ещё можно как асинхронный метод определить

  • @user-dh4qw7qz8v
    @user-dh4qw7qz8v Před rokem +1

    Правильно понимаю, что инициализируемые объекты в первой сцене мы должны определить в DontDestroyOnLoad ? Чтоб они были доступны и в другой сцене?

    • @gamedevlavka
      @gamedevlavka  Před rokem

      Это зависит от архитектуры, но да, один из вариантов в DontDestroyOnLoad()

    • @user-dh4qw7qz8v
      @user-dh4qw7qz8v Před rokem +1

      @@gamedevlavka Но это то, что мне первое в голову пришло. Теперь встал вопрос, как еще можно обеспечить доступность, того же Zenject и в других сценах, наиболее распросраненные практики?

    • @HizusHiz
      @HizusHiz Před rokem +3

      @@user-dh4qw7qz8v Zenject уже есть свой подход, что здесь называется Entry Point - называется Context. Есть Project Context и Scene Context'ы. То есть все что здесь рассказано, можно через Zenject фреймворк делать. Подробнее в самой документации Zenject

    • @gamedevlavka
      @gamedevlavka  Před rokem +1

      @@HizusHiz можно, при этом в Zenject есть и ручная инициализация, что превращает его в инструмент, а не контроллер. Такие подходы тоже использовал, не всегда внутри zenject можно эффективно контролировать порядок. Так что тут все гибко, но в целом да, можно EntryPoint и через контекст в Zenject делать

    • @HizusHiz
      @HizusHiz Před rokem

      @@gamedevlavka да, согласен, что при этом надо учитывать нюансы реализации фреймворка, что не всегда удобно

  • @vladislavsatanov6548
    @vladislavsatanov6548 Před 11 měsíci

    Делал по этому подходу игру zigzag выходит прикольно, все удобно и очень понятный код для изменений и расширений, но когда я дошел до OnCollision и похожих методов то понял, что не могу таким подходом сделать банальную вещь как проверить коснулись ли объекты друг друга, так как такие методы по умолчанию принимают в параметр объект на котором висит скрипт. Может есть какой-то другой подход при единой точке входа.

    • @gamedevlavka
      @gamedevlavka  Před 11 měsíci

      А в чем проблема? Объект на котором висит скрипт есть, OnColission есть, если сработал, значит столкнулись. Не пойму в каком месте проблема?

    • @vladislavsatanov6548
      @vladislavsatanov6548 Před 11 měsíci

      @@gamedevlavka OnCollisionEnter у меня в классе "инпутпоинт" объекты передают через инспектор, но чтобы OnCollisionEnter сработал он должен висеть на объекте с РБ и коллайдером и выходит что он просто не срабатывает.

    • @gamedevlavka
      @gamedevlavka  Před 11 měsíci +1

      @@vladislavsatanov6548 что-то ты не так понял концепцию. Монобехи и скрипты на них существуют и живут себе на сцене. В том числе некий скрипт, который висит на объекте с RB, который будет триггерить колизию. Он же в свою очередь может прокидывать событие выше в бизнес логику, например: столкнулись два объекта и у них должны отняться жизни, вот они в бизнес логику и говорят:
      SomeFeature.ObjectsCollide(object1, object2)
      Это как пример. И все

    • @vladislavsatanov6548
      @vladislavsatanov6548 Před 11 měsíci

      @@gamedevlavka Спасибо, попробую.

  • @SanAndys
    @SanAndys Před rokem

    мне видится, что это не патерн, а больше как некая техника.
    "стартуй в одной точке". это хорошо, полезно и актуально для начинающих.
    доростут дальше - будут использовать Zenject.
    -
    снимайте плиз и дальше видео на аудиторию с разным уровнем. многим новичкам это полезно.

    • @gamedevlavka
      @gamedevlavka  Před rokem

      Некая техника - и есть паттерн. Паттерн это принцип, техника, шаблон действий. Так что тут все ок.
      Насчёт зенжекта - он также реализует этот паттерн. А если нет, то у меня для вас плохие новости, зенжект значит используется неэффективно и странно)
      ___
      Спасибо, буду стараться)

  • @C_o_A
    @C_o_A Před 4 měsíci

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

  • @xagent
    @xagent Před rokem +4

    Можно не дергать окна интерфейса туда-сюда во время разговора? Честно говоря раздражает))

    • @-unity-
      @-unity- Před 7 měsíci

      Поддерживаю!

  • @evggg
    @evggg Před rokem

    А как при таком подходе инициализировать сервисы, которые о своей готовности сообщают в колбеках? Как колбеки стыкуют с корутинами? Ну и плюс при таком подходе, получается, придется всеми объектам на сцене вешать какой-нибудь скрипт, который будет блочить их деятельность, пока инициализация до них не дойдет и не запустит их. Как будто геморройненько звучит.

    • @gamedevlavka
      @gamedevlavka  Před rokem +1

      1. Запускаешь корутину, асинк что-то асинхронное, чтобы подождать пока сервисы проинициализируются и будут готовы. Вариантов на самом деле множество, нужно проявить смекалку и подобрать наиболее подходящий в текущей обстановке.
      2. Не нужно всем объектам вешать никаких скриптов, они должны приводиться в рабочее состояние через инициализацию, не они кого-то ждут, чтобы запуститься, а их запускают, когда это необходимо

  • @VitegO4
    @VitegO4 Před rokem +3

    ударение режет слух, па́ттерн

  • @user-qb8lx2uq5j
    @user-qb8lx2uq5j Před rokem

    Это настолько интуитивно понятно и очевидно, что удивительно, если кто-то не "изобрел" этот паттерн сам и пытался подготавливать фичи в своей игре как-то по-другому.

    • @ichbinschlange
      @ichbinschlange Před rokem +2

      Да много кто пытался по-другому. Я пытался по-другому:
      Сначала куча MonoBexxx, каждый на объект, ссылки пробрасывал эдитором (поскольку Unity допускает YOLO-подход, а всякие туториалы для простоты демонстрируют именно его, возникало ощущение, что так и надо).
      Далее, когда даже небольшой проект превратился в лютую срань (кто бы мог подумать), подход изменился на "Одна фича - один объект" (по-моему какой-то из обучающих Unity проектов (которые с хаба докачиваются) демонстрировал тоже самое), жить стало проще.
      Далее довелось поработать не с Unity, никакого крепления скриптов на GameObjectы, естественно, не было (как и самих GameObjectов) и только тогда пришло понимание, как нужно делать.
      Для тех кто начинает с Unity ни разу не очевидно, что должна быть какая-то точка входа.

    • @gamedevlavka
      @gamedevlavka  Před rokem

      @@ichbinschlange Абсолютли эгрии, сам через такое же прошел, не рекомендую :)

    • @andrey_aka_skif
      @andrey_aka_skif Před rokem

      @@ichbinschlange дело не в самом Unity. Вы верно заметили, что официальные туториалы в основном игнорируют архитектурные вопросы. Или подают их очень своеобразно.

    • @ichbinschlange
      @ichbinschlange Před rokem

      @@andrey_aka_skif, нож только инструмент, это ясно, но тут как-то не возникает мысль, будто делаешь что-то не то, пока не случается затык. За это хочется упрекнуть движок. Те же нативные андроид-приложения пляшут от сцены (от откна, в рамках разработки) и не только они, Microsoft-технологии поступают так же.

    • @andrey_aka_skif
      @andrey_aka_skif Před rokem +1

      @@ichbinschlange MVVM это тоже своеобразная вещь. Её смысл понятен, но паттерн загоняет тебя в определенные рамки. Шаг в сторону, и тут же жесткий тупняк. Особенно, если ты не разработчик подобных приложений, а захотел сделать небольшой специфичный инструмент.

  • @NewUser78654
    @NewUser78654 Před rokem

    Данный паттерн проектирования не описан в гоф, что делает его использование весьма сомнительным. В Википедии более 100 паттернов и антипаттернов и почти каждый программист пробует написать свой паттерн.
    Данный паттерн применяется в веб разработке (возможно, отсюда пошло красивое название точки входа как бутстрап?). Напомню, что в веб мы посылаем и получаем данные, т.е. генерация данных каждый раз происходит с нуля (есть варианты - догрузка данных - аджакс, реактивные фреймворки, но не суть).
    Это особенность работы веб приложений.
    В десктопных программах, какой и является юнити (мы же генерируем игру для десктопа?), мы имеем почти все данные у себя на компьютере. Поэтому использование данного паттерна не является необходимым. Мы можем проинициализировать всё сразу и один раз.
    Один раз загрузить в память все менюшки, один раз загрузить настройки игрока. У нас всё уже есть на локальной машине - нам никуда не надо делать постоянные запросы, загружать данные по требованию пользователя. Уверен, что на менюшки и настройки игрока и прочую мелочь хватит памяти современных устройств.
    Более того - юнити всё грузит сам. Текстура на объекте, а объект на сцене? Много объектов, коллайдеров ..чего угодно. Когда мы загружаем сцену, мы же не пишем - загрузи объект 1, загрузи коллайдер на объекте 1... мы пишем - юнити загрузи сцену, а юнити сам всё загружает. Нам осталось только написать корутину проверки процента загрузки сцены и вывести это как прогрессбар.
    В конце добавлю, что такое разбиение, особенно присвоение игроку инпута, инвентаря "извне" нарушает принципы ООП, а конкретно инкапсуляцию.
    В конечном итоге произойдет путаница в инициализациях, зависимостях, последовательностях.

    • @gamedevlavka
      @gamedevlavka  Před rokem +7

      Интересно, как вы приклеили свои домыслы к моему видео. Вы можете относиться к паттерну как угодно, я никого не заставляю его использовать. Но личная статистика такова: на более чем 80% проектов (выборка более 30 проектов) был использован паттерн единая точка входа.
      Не нужно думать, что современные устройства потянут "все, что угодно". Мобильная разработка (которая превалирует над всеми остальными платформами) диктует правила оптимизации. Оптимизация на мобилках это очень большой раздел знаний разработки на юнити, и расписывать его здесь я не стану, информацию модно найти при желании.
      Очень похоже, что опыта в работе над крупными проектами у вас либо нет, либо недостаточно, чтобы понять, чем опасна хаотическая инициализация подсистем. Да, юнити грузит часть ресурсов самостоятельно, и это сильно упрощает некоторые процессы. Но это лишь один из аспектов инициализации.
      Совершенно не понял, каким образом инициализация игрока с инпутом нарушает инкапсуляйию. Я и слова не сказал о том, как это реализуется. Всё, что вы сказали - это какая-то ваша фантазия, которой вы не поделились

    • @andrey_aka_skif
      @andrey_aka_skif Před rokem +4

      Вот с этого места подробнее. В чём же присвоение извне нарушает инкапсуляцию? А как же инверсия управления из SOLID и внедрение зависимостей? А TDD как же?
      Про веб тоже интересно. Веб разве ограничен фронтом? А как же бэк? В asp.net приложение стартует аналогичным образом. Билдер собирает приложение из сервисов, только потом запускает. Такая сборка происходит не при каждом обращении к контроллеру, а именно при старте приложения.

    • @NewUser78654
      @NewUser78654 Před rokem

      @@andrey_aka_skif а вы не задумывались что наследование нарушает инкапсуляцию? Тем более все перечисленные вами методики.
      А вы про солид...
      Очень частая ошибка мидл разработчика, яростно увлеченного паттернами (нет, не толкать их куда не надо он эту стадию уже прошел), а пытаться применять их во всех областях, технологиях и решениях.
      Про веб - скажите asp нет пхп пайтон что то там ещё собирает все свои модули где? Оно загружает модули и исходный код (нет ну а вдруг) на клиентскую машину пользователя, подымает там локальный сервер и отображает страницу или...или всё делает у себя, а пользователю отдает только хтмл, картинки, жс скрипты. Нам не надо ничего собирать в юнити - у нас всё тут.

    • @NewUser78654
      @NewUser78654 Před rokem

      @@gamedevlavka У меня есть ещё пара фантазий. Не писать имена полей и переменных начиная с _ _isLoading и перестать писать f как магическую букву в конце значений переменных. Есть спецификация языка и стандарты майкрософт. Есть язык со строгой типизацией. Вам всё дали - пользуйтесь.

    • @user-qb8lx2uq5j
      @user-qb8lx2uq5j Před rokem +3

      @@NewUser78654 Без f в конце литералов для float переменных вообще-то не скомпилируется ничего, это как раз требование спецификации языка. По поводу префикса для private полей вот выдержка из свежего соглашения микрософта: "Используйте верблюдовый регистр ("camelCasing") при именовании private, internal полей и добавьте к ним _ префикс"

  • @esteticachannel4604
    @esteticachannel4604 Před 9 měsíci +2

    Контексты зенжекта и есть ентри поинт

  • @zloybivshiy7236
    @zloybivshiy7236 Před 10 měsíci +1

    Спасибо за видео!