До релиза игры остался месяц, я решил переписать ее полностью...(

И у меня получилось!


На связи снова я со своим маленьким космо-шутером с видом сверху с честными орбитами, гравитацией и космодробовикам, имя которому HOTLOOP.

На этот раз я решил затронуть тему программной реализации, а именно внедрения контейнера зависимостей, его величества Zenject (т.к. игра на Unity)!

С самого начала разработки основное внимание уделялось только геймплейным механикам, чтоб кораблики летали, пушки стреляли, а гравитация работала как и в реальности. В итоге такой подход привел к тому, что во всей игре было только три уровня: Главное меню, летная школа и орбита планеты. Большего ведь для тестирования геймплея не нужно... И надо признаться они справлялись с задачей, к которой готовились, а именно к участию в фестивале демок в steam "Играм быть"!

Фестиваль прошел, демка игры кое-как отработала, и принесла каких то вишлистов и теперь нужно было двигаться дальше. Но из-за того как именно был реализован весь проект, задача создания новых уровней из максимально приятного ctrl+c ctrl+v превращалась в ужаснейшую рутину по перепривязыванию одних объектов к другим.

Суть проблемы

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

Для решения именно этой проблемы, умными дядьками была создана концепция автоматического "внедрения зависимостей". Специальный скрипт знает какой объект в сцене является кораблем игрока, и может передать ссылку на него любому другому нуждающемуся объекту. Таким образом, при замене планеты на станцию, больше нет необходимости указывать ей кто тут ̶п̶а̶п̶о̶ч̶к̶а̶ игрок!

Далее хочу привести несколько рекомендаций по разработке проекта с прицелом на внедрение zenject (и возможно аналогов тоже).

1 - Внедряй zenject сразу. Если тебе не хочется внедрять его сразу, то тебе кажется, и на самом деле тебе хочется внедрять его сразу!

2 - Если ты всетаки проигнорировал п.1, и теперь тебе, как и мне нужно перелопачивать почти весь проект, не спеши сразу все делать на живом проекте\в основной ветке разработки. Если используешь Git, сделай отдельную ветку и экспериментируй в ней. Если не используешь гит (осуждаю), то сделай бекап проекта в отдельной папке, чтоб у тебя всегда была возможность вернуться в точку, где zenject-а еще нет.

3 - Сведи использование UnityEvent и рефок на объекты в инспекторе (как на скрине ниже) к минимуму. В них ты будешь прокидывать связи на конкретные объекты, а это как раз случай с планетой, станцией и игроком, описанный мной выше! Это допустимо разве что только для ссылок на самого себя.

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

5 - Уже в процессе перевода на зенжект, когда ты заменяешь UnityEvent на инъекцию через контейнер, тебе захочется скрыть эту этот ивент из инспектора, ведь он вроде как теперь бесполезен. НЕ ДЕЛАЙ ЭТОГО. Оставь пока не убедишься что на ВСЕХ сценах ты пересобрал логику из ивента с использованием контейнера!

6 - Так же если зенжект внедряется в уже полу-готовый проект, как в моем случае, ты наверняка узнаешь, что по канону, зенжект должен сам создавать объекты которые покрывают зависимости (в нашем случае это корабль игрока, который являлся зависимостью для планеты и станции), следовательно казалось бы, их можно удалять со сцены после описания инъекции. НЕ ДЕЛАЙ ЭТОГО... просто не делай. Иначе добавишь себе головную боль с порядком регистрации зависимостей. По феншую сделаешь уже на новом проекте!

Ну и по класике!

Поговаривают, что у добавивших мою игру в желаемое FPS во всех играх увеличивается на 10 единиц, а PP получает +1см к длине. Думаю тебе стоит проверить эту гипотезу!

Слыш ̶к̶у̶п̶и̶ добавь в желаемое

14
521

Комментарии

ааа так вот она откуда в вш

ааа так вот она откуда в вш
zkiroel
ааа так вот она откуда в вш

Это про что речь? Чот я не в теме. Что за "вш"?

Это про что речь? Чот я не в теме. Что за "вш"?
zaicev9797
Это про что речь? Чот я не в теме. Что за "вш"?

Вишлист

Вишлист
Xander Grishchenko
Вишлист

гыг)

Я немножко суть проблемы не понял

В чём проблема сделать что-то вроде

Init

If (player.exists) target = player

?

Я немножко суть проблемы не понялВ чём проблема сделать что-то вродеInitIf (player.exists) target = player?
Gab125
Я немножко суть проблемы не понялВ чём проблема сделать что-то вродеInitIf (player.exists) target = player?

Проблема в том чтобы найти "player" в игровой сцене

Проблема в том чтобы найти "player" в игровой сцене
zaicev9797
Проблема в том чтобы найти "player" в игровой сцене

Тег player? Да хоть по имени

Тег player? Да хоть по имени
Gab125
Тег player? Да хоть по имени

Так лучше не делать. Тег может технически висеть на нескольких объектах, и тогда не известно какой именно тебе нужен. Это еще ок если проект крошечный., но если разрастется хотябы до просто небольшого или среднего, то это станет большой проблемой. Так же и с именем. Вопервых это очень медленно, а во вторых может вызвать проблемы если кто то по неосторожности или не знанию переименует сущность. Очень критично если работать в команде. Хоть я и делаю игру один, но стараюсь привить себе привычки командной работы, так, чтобы потом с этим не было проблем.

Так лучше не делать. Тег может технически висеть на нескольких объектах, и тогда не известно какой именно тебе нужен. Это еще ок если проект крошечн…
zaicev9797
Так лучше не делать. Тег может технически висеть на нескольких объектах, и тогда не известно какой именно тебе нужен. Это еще ок если проект крошечн…

Так суть тега player в том, что он висит ТОЛЬКО на одном объекте, но хорошо, если это медленнее, тогда в чем проблема передать с игрока реф на себя при посадке?

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

Так суть тега player в том, что он висит ТОЛЬКО на одном объекте, но хорошо, если это медленнее, тогда в чем проблема передать с игрока реф на себя п…
Gab125
Так суть тега player в том, что он висит ТОЛЬКО на одном объекте, но хорошо, если это медленнее, тогда в чем проблема передать с игрока реф на себя п…

Тут скорее проблема в том, что при использовании тегов нет "защиты от дурака". Кто то может поставить тег на две сущности, когда это не предусмотрено по программной логике. Тег может быть переименован и тогда везде в коде надо будет тоже это передергивать.

Не всегда можно просто "передать реф". Например некоторые объекты должны быть доступны на самом старте сцены. Более того. некоторые объекты могут быть необходимы для инициализации других объектов также на старте. В этот момент появляется необходимость контролировать порядок выолнения скриптов, т.к. нельзя инциализировать обьект, пока не проиницииализированы объекты от которых он уже сам зависит.

Иньекция же зависимостей это решает автоматически.

Тут скорее проблема в том, что при использовании тегов нет "защиты от дурака". Кто то может поставить тег на две сущности, когда это не предусмотрено…
zaicev9797
Тут скорее проблема в том, что при использовании тегов нет "защиты от дурака". Кто то может поставить тег на две сущности, когда это не предусмотрено…

А кто-то может стереть весь код, удалить весь проект и т.д. Глупость же

Всё равно не могу представить примера проблемы, где это не решается изначально продуманным дизайном проекта или чуть другим подходом, ну да ладно

А кто-то может стереть весь код, удалить весь проект и т.д. Глупость жеВсё равно не могу представить примера проблемы, где это не решается изначально…
Gab125
А кто-то может стереть весь код, удалить весь проект и т.д. Глупость жеВсё равно не могу представить примера проблемы, где это не решается изначально…

если использовать гит, то никто кроме влаельца репозитория не сможет стереть код)

Так суть тега player в том, что он висит ТОЛЬКО на одном объекте, но хорошо, если это медленнее, тогда в чем проблема передать с игрока реф на себя п…
Gab125
Так суть тега player в том, что он висит ТОЛЬКО на одном объекте, но хорошо, если это медленнее, тогда в чем проблема передать с игрока реф на себя п…

проблема передать с игрока реф на себя при посадке?

Так Зенжект по сути это и делает. Зенжект это просто реализация DI, с которым разобраться куда проще, чем делать самописный.

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

оверинжиниринг для выдуманной проблемы

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

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

Ну, кстати, сейчас почти везде, даже на джунов Unity требуют уметь работать с зенжектом :D

проблема передать с игрока реф на себя при посадке?Так Зенжект по сути это и делает. Зенжект это просто реализация DI, с которым разобраться куда про…
Cocojombruh
проблема передать с игрока реф на себя при посадке?Так Зенжект по сути это и делает. Зенжект это просто реализация DI, с которым разобраться куда про…

>разобраться куда проще

Кому как, видимо

Я любые фреймворки не перевариваю, из-за них всё становится только сложнее

>Прокидывание зависимостей это один из главных архитектурных вопросов на юньке

Более точно - это решение проблемы, которую изначально можно было легко избежать

>разобраться куда проще Кому как, видимоЯ любые фреймворки не перевариваю, из-за них всё становится только сложнее>Прокидывание зависимостей эт…
Gab125
>разобраться куда проще Кому как, видимоЯ любые фреймворки не перевариваю, из-за них всё становится только сложнее>Прокидывание зависимостей эт…

Имея пятилетний опыт в продуктовой разработке (на пхп), могу отметить, что DI используется там серьезными дядьками очень плотно, что наводит на мысль, что это один из наиболее удачных способов решения подобных проблем.