Григорий Дядиченко – Telegram
Григорий Дядиченко
2.82K subscribers
395 photos
160 videos
7 files
1.2K links
Разработчик игр, интерактивных стендов и интерактивной рекламы. Эксперт в области интерактивов и XR.

100+ проектов за 5 лет.

По вопросам сотрудничества писать: @it_bizdev
Реклама в канале: https://vk.cc/cNhGLE
Download Telegram
Референсы и насмотренность

У разных профессий различные проф деформации. Например во времена работы геймдизайнером я разбирал любую игру на механики автоматом. Но в графике я считаю одну привычку очень полезной — собирать рефы. В интернетах они есть не для всего. У меня когда-то был целый каталог видео допустим дождя в луже, чтобы смотреть на поведение капель воды)

Но видео это видео, камера передаёт всё немного искажённо, так что ещё полезно внимательно смотреть по сторонам. На деревья, архитектуру и какие-то природные явления. Меня вот всегда интересовал fog в юнити и почему он так рисуется, а на этой неделе я впервые побывал в горах и теперь — понятно :)
🔥1
Базовые ошибки фрилансеров

Как технический продюсер, которому сейчас периодически нужны рабочие руки я отсматриваю очень много фрилансеров. И замечаю их банальные ошибки. Помимо этого я был с другой стороны баррикад) Я в течении 2 лет фрилансил разработку со ставкой 2к/час. И если вы хотите держать такую ставку, адекватных заказчиков и в целом, чтобы с вами хотели работать вот набор простых правил)

1. Никогда не «придирайтесь» к заказчику

Объяснять что-то заказчику с точки зрения экспертности — нормально, напрямую несоглашаться — лучше мягко, но тоже можно. Не в стиле «вы нихера не знаете, я тут эксперт», а «я бы рекомендовал сделать так». Занудствовать и поправлять в мелочах — никогда. Как-то раз я писал с телефона и мне указали на орфографическую ошибку в тексте, и тут как бы вопрос «а зачем, как это поможет сотрудничеству?» Это причём довольно частая ошибка :) Если вы хотите успешно что-то кому-то продавать, так делать нельзя :)

2. Заказчик не обязан вам что-то объяснять

Основная работа чтобы всё прошло с заказом спокойно, это предпродакшен или подготовка. Тут нужно примерять роли бизнес аналитика и дотошно выяснять все детали, если заказ на конкретный объём и функционал. Я чаще сейчас в работе обозначаю рамки времени работы, так как я +- понимаю, что сколько делается, как технический директор и профильный заказчик сделавший больше 50 проектов :) А непрофильные заказчики не знают чего хотят, это надо выяснить и зафиксировать) И всё будет спокойно. Мне много кто рассказывает про ад с заказчиками, я с этим сталкивался редко, так как просто не допускал на этапе согласования разночтений. Хотя конечно не скажу, что такого не бывает

3. Не работать с мудаками

Честно говоря, я очень избирателен в заказчиках, и сейчас уже в разы больше отказываюсь, чем соглашаюсь. Как показывает практика любой заказ с неадекватами, как ты бюджет не выкручивай штука нерентабельная. С хорошими заказчиками я иногда делаю просто огромные скидки, когда им «нужна помощь», с средними всё по стандартному процессу. С мудаками, доделать то, о чём договорились и забыть

4. Никогда не пропадайте

Это уже со стороны продюсера. Очень многое можно обсуждать. Если вы работаете с продюсером или хорошим ПМ, это его задача придумать, как мы выкручиваемся. Всякое бывает. Проебались, заболели, переоценили силы. Главное говорить и обсуждать. С кем я работал, и кто проебался но не пропал, я всегда работаю дальше. Если человек пропал и меня подставил, я как продюсер решу проблему, но это вечный блок подрядчика

5. Желание делать работу

Меня удивляет, когда мне приходится упрашивать людей что-то сделать) Ну это исходя из моего опыта. У меня бывали разные истории, конфликты и т.п. но заказчики всегда возвращались, так как знали что я сделаю, и я хотел работать. Если заказчик мне написал, то пока он не скажет «отмена», я буду ему писать каждую неделю «что как?». А часто я получаю отклик и дальше неделю вылавливаю человека. Я опять таки продюсер, поэтому я этим занимаюсь. Но непрофильные (да и многие профильные) заказчики этого делать не будут)
6
Прикольно, на вершине ловит LTE :) #гамсутль Тяжел труд продюсера :)
👍5
Хорошо организованная иерархия — это важно

В целом не стоит недооценивать важность дисциплины в организации проекта. С хорошей структурой папок проще работать. С хорошей организацией иерархии сцены проще работать. В целом достаточно выработать один раз удобную вам структуру, чтобы потом всегда делать по лекалу и нигде не путаться. Тут главное не лениться, так же как и с неймингами объектов. Потому что когда всё проименовано по какой-то логике и схеме проектом проще управлять

В плане структуры папок я предпочитаю:
Assets:
Scenes: сцены
Scripts: скрипты
Core: основная логика
UI: скрипты интерфейсов
Plugins: плагины
External: все внешние ассеты
Sources:
Prefabs: префабы
Shaders: шейдеры
Textures: текстуры
Models: 3d
Materials: материалы
UI: интерфейс
Backgrounds: задники
Icons: иконки
Buttons: кнопки

Вариации бывают только в Assets/Sources/UI и также исключением является папка Resources но это чистой воды оптимизация. Там могут лежать Scriptable Objects, которые ссылаются на префабы и т.п. Лежат они там, так как доступ к ним нужен по пути, чтобы правильно асинхронно грузить сцену. В юнити есть такой нюанс. Если в сцене есть ссылка скажем на SO, в SO на какой-то префаб в котором лежит модель. То при загрузке сцены вы загрузите в память модель и всё на что есть ссылки. Даже если оно не инстанцировано, и это логично. Поэтому иногда нужен доступ к ресурсам по путям. Но проще оперировать SO, где лежат группы нужных префабов

Что же касается иерархии я привык для чистоты заводить папочки, вроде [MANGERS] или [UI], где внутри уже будут под каталоги, если объектов слишком много. Так проще не путаться, проще редактировать командой (Вынеся папку в префаб), да и быстрее что-то находить

В общем структура — это важно, и очень ускоряет работу
👍2
Да, к прошлому посту. Почему лучше не хранить все исходники в ресурсах. Если коротко, сложнее вычищать при росте проекта ненужные ресурсы. В ресурсах должно лежать только то, что прям очень важно грузить по путям, а остальное лучше хранить вне этой папки. Потому что если вдруг какой-то ресурс не используется в сценах, то если он лежит вне папки ресурсов, то он не пойдёт в сборку автоматически. То есть для примера вы удалили из сцены префаб, который лежит не в ресурсах, и всё на что он ссылается. Все эти ассеты включая сам префаб автоматически не пойдут в билд :)
Я понял, что я очень надеюсь, что эпл обяжут пустить альтернативные сторы и вот почему)

Должна упростится дистрибуция

Сейчас при работе с эплом главным неудобством является дистрибуция. Нельзя просто собрать ipa архив и доставить его пользователю. Есть вариант с ad hoc, но там нужен заранее заготовленный список устройств, что не всегда удобно и реально. Есть вариант тестфлайтом, но там вообще нужно конкретных людей добавлять по эпл айди. Есть вариант с энтерпрайсом, но так как там приложение могут устанавливать «только сотрудники», то тоже свои нюансы

В случае введения альтернативных стров эплу придётся либо со всеми сторами договариваться, чтобы не ломать систему. Либо давать возможность качать ipa в обход неё :) Плюс не будет монополии на ревью :)
#концепт

Прикольно было бы, если бы у скажем банковских приложений был «сотовый режим». Там конечно возникает очень много вопросов, в первую очередь в плане безопасности и стоимости этого дела с авторизацией. Но иногда есть сотовая связь, но нет интернета. У некоторых банков есть переводы через смс, но посмотреть инструкцию без интернета я не могу, а в приложении без интернета она не выводится :)

Но представим что была бы кнопка с механизмом авторизации и возможностью перевода денег через gsm) В местах где бывают проблемы с интернетом, типа тех же гор — это было бы весьма удобно) Надо кому-то перевести скажем срочно, нажал несколько кнопок, улетели автоматом несколько смс, операция прошла и всё замечательно :) Технологически по идее в этом нет никаких проблем, кроме возможно политик безопасности платформ в плане «отправить смс автоматом». Не могу погуглить и посмотреть, пока не очень с инетом :)
👍1
Несовершенство компьютера

Есть много забавных ошибок, которые возникают из ограничений возможности компьютера в целом. Моих любимых пожалуй две, но суть у них одна :) Важно помнить, как работают простые типы. Поговорим про float. Я не буду говорить про неточности суммирования и строгие условия, это слишком банально и многие IDE сейчас подсвечивают :) Основное что надо помнить, что хранить он может 6-7 знаков. И из этого у новичков возникают забавные ошибки :) Почему в юнити float, а не double — это довольно долгий рассказ, может как-нибудь потом опишу :)

Получать gps координаты в float. Мало того, что gps сам по себе страдает в плане точности. И это конечно не критично, но важно знать, что будет если перегонять точку в float (что делают на удивление часто) Можно ли писать в float? В целом да, особенно при работе с навигацией, так как точность gps достигает 20 метров и зависит от широты и оборудования рядом (https://support.google.com/maps/answer/2839911?hl=ru&co=GENIE.Platform%3DAndroid) В Москве допустим точность около 5-6 метров. И когда вы округляете координаты до 7 знаков у вас получается точность страдает значения от примерно 80 сантиметров до 8 метров (так как долгота бывает трёхзначной) :) Что в целом ок, хотя лучше иметь ввиду, так как вы добавляете ошибку в несколько метров) Но всё же в кейсе навигации это не критично, а вот в расчёте расстояний ещё как важно. Так как обычно для этого хранятся 7 знаков только после запятой :)

Перемещать игрока в бесконечном мире. Ну тут та же забавная проблема. В бесконечных мирах есть много трюков, но если просто перемешать игрока не используя их, то проблема в позиции (1234567, 123467) мне кажется очевидной. У вас просто не будет работать дробная часть, и будет ошибка округления в 1 :) И там можно доводить до абсурда) А допустим 1 в вашем мире — это один метр) Почему же тогда в Unity float, а не double с его 15 знаками? Они что дураки?) Не, там всё довольно логично, но как я и говорил — это длинная история :)
🔥2
Настоящим профессионалам не нужно наводить туман

Как легко отличить настоящего профессионала? Он не пытается запутать вас терминами и может объяснить что угодно на пальцах. Я очень не люблю, когда фразы типа иммутабельности, консистентности и т.п. используют что-то объясняя не профессионалам. Я часто сталкивался одно время с тем, что люди не могут объяснить зачем скажем нужен солид своими словами, а не цитатами из книжки)

Если человек в чём-то разбирается, он всегда это может объяснить это на пальцах. Мне когда-то понравилось в этом плане объяснение старого (уже почти мемного) вопроса с собеседований «Чем интерфейс отличается от абстрактного класса?» Правильный ответ по сути звучит, что интерфейс объединяет поведение и стандартизует апи обращения, а абстрактный класс — это обобщение свойств объектов. Но без примера для меня это когда-то звучало, как просто набор букв. Но в одной статье на хабре был дан просто шикарный пример. У кота, собаки и мыши — есть лапы (свойство объекта), а у ключа, ключ-карты и лома — возможность открывать двери (поведение) :)

Сложная терминология чаще всего просто сокращает объяснение до пары фраз. Как и паттерны. Сделай тут команду, а это сделай декоратором, а тут лучше фабрика подойдёт — упрощает коммуникацию. Но когда вы пытаетесь что-то объяснить, а не поставить задачу другому эксперту, говорить нужно человеческим языком :) Многие из новичков ещё и стесняются говорить, что то что вы им сказали — это белеберда на эльфийском :)
Григорий Дядиченко
Кстати, хотел узнать. Интересны ли были бы кому-нибудь такие темы? И какие наиболее интересны
Паттерн Команда

Чтож, в опросе победили паттерны, давайте посмотрим на один из моих любимых паттернов — команда. Это прикольный поведенческий паттерн, его красивое определение с диаграммой можно почитать тут https://metanit.com/sharp/patterns/3.3.php я же хочу показать пример на Unity и сказать зачем он может быть нужен. Для выразительности пример будет упрощённый, так как архитектурно в целом я бы делал бы немного иначе)

Но сначала предыстория) 3 года назад я работал в одной компании, и мы много времени 3д моделеров тратили на тупую задачу — сделать коробку с окнами. Пробилдера тогда не было, да и в целом хотелось чего-то поудобнее. И тогда я придумал https://github.com/Nox7atra/Apartment_Builder Но так как я не был таким опытным, я не додумался до одной вещи) Собственно до того, что в ядро любого разрабатываемого редактора нужно класть паттерн команда, чтобы поддержать всего лишь один функционал) ctrl+Z :) Если ядро сделано с ним, то это делается тривиально)

Если коротко паттерн команда приколен многими вещами) В зависимости от глубины реализации он позволяет вам делать какие-то действия отложенно, откатывать их, хранить историю действий и т.п. Это очень удобно для всякого рода редакторов, пошаговых игр (можно легко делать проигрыватель геймплея, хранить реплеи если делать так) И т.п. Я люблю его использовать для читов, консольных команд и многого другого. Плюс его удобно логировать и в целом выводить историю. Чтож. Простой пример, как и обещал) Я решил на тему паттерновых историй завести целый репозиторий (потом напишу к нему ридми) https://github.com/Nox7atra/PatternsUnityPlayground

Разберём на простом примере — крестики-нолики. В целом мой любимый пример для обучения новичков чему-либо) Итак, сама по себе команда — это по сути объект умеющий делать две работы. Выполнять работу и откатывать работу, поэтому у нас для неё есть интерфейс ICommand с методами Execute и Undo (всё можно найти в репе). Как и в редакторе действия у нас строго последовательны. И их надо как-то хранить и выполнять. Как и для редакторов я люблю конструкцию со стеком StackCommandInvoker. По сути мы пишем все команды в стек, чтобы потом иметь возможность откатить их строго в той последовательности, в которой мы их выполняли. Чтож осталась игра)

В крестиках-ноликах очевидно, что командой у нас является ход пользователя. Ресивер для упрощения — сама игра. Поэтому остаток реализации можно посмотреть в репозитории выше именно в виде кода в классах CrossGame и PlayerTurnCommand. Ну я тут немного поговорю про идеологию. Вот мы всё это сделали, и теперь что нам это даёт? По сути так как команды отлично в этом паттерне сериализуются, то можно сделать откат на любое число шагов, реплей игры и т.п. Сохранить партию и т.п. И это позволяет просто правильно и вовремя заложенный паттерн команда) Очень рекомендую :)

P.S. Возможно более подробный разбор стоит составить в статью на хабре. С кодом и построчно) Но это так сказать пробный пост из первых рук. Предлагаю устроить простое голосование, кому интересна эта тема. 👍 — значит такой формат "по горячим следам из первых рук" вести тут, 🔥 — значит лучше разбирать подробнее и на хабре :) Со статьями на хабре есть одна проблема, на них прям нужно находить время, так как там требуется соблюдать более строгий формат и больше нюансов по оформлению, так что там я по своей загрузке смогу писать, но только пореже)

Плюсы паттерна команда:
1. Просто делать ctrl+Z если надо
2. Просто делать реплеи
3. Просто делать отложенные действия и непрямой геймплей
4. Просто сериализовать все действия в файлы, чтобы потом это дело вынести на сервер или в сейв
👍12🔥3
Как стоит относиться к архитектуре, паттернам и т.п.

Раз у нас тут вечер архитектуры, то ещё надо сказать моё к ней отношение. Стоит запомнить, что программирование — не является точной наукой. Все холивары выглядят довольно забавно, когда немного меняешь взгляд на разработку в целом. Разработка процесс творческий. Паттерны, SOLID и прочие прелести разработки были придуманы не для того, чтобы спорить о том "а что лучше". А для того, чтобы ими пользоваться. Паттерн — это базовый шаблон. Его не то чтобы можно реализовать неправильно, если просто соблюсти базовый концепт и то зачем он нужен. У вас может быть своё расширение над паттерном. SOLID — это не строгая инструкция "как правильно и хорошо программировать", а просто набор рекомендаций. Который строго говоря не всегда применим. Так же, как и ООП, ФП. Дактайпинг или статическая типизация и т.п. Иногда кажется, что программисты дольше спорят вместо того, чтобы просто пользоваться и творчески подходить к задачам с инструментами, которые им когда-то оформили и дали в руки)

Я в целом думаю, что частичная проблема этого, что многие программисты в прошлом технари. А технари чаще сталкиваются с точными науками. В математике каждая запятая в формулировке важна, строго значит одно и математики дико педантичны в том, чтобы поправить. Потому что чаще всего неправильная формулировка означает непонимание вопроса. Но в программировании — это вообще не так работает, так как программирование не точная наука. Я видел и огромные системы на синглтонах (которые хорошо работали и нормально поддерживались) и много чего ещё. А видел и откровенное мракобесие "с архитектурой". Где фабрика едет через фабрику, фабричным методом погоняя. И всё супер абстрактно, и я то могу вытерпеть распутывание этого клубка "супер абстракций" с бутылкой джина :) Иначе сразу лучше в дурку)

Старый принцип KISS на первом уровне проще всего соблюдать так. Не придумывайте сложных абстракций. Человеческий язык не совершенен и не всегда получается правильно другому человеку донести свои мысли обычными словами. Но когда в программу закладывается может быть очень крутая идея, но она — сложная. Высок риск, что другой человек её просто не поймёт. Почти всегда не нужно руководствоваться абстракциями программирования, паттернами и т.п. и не городить красивую "всё умеющую башню абстракций". А нужно руководствоваться обычной и такой простой человеческой логикой) Она остальным программистам будет более понятна) Конечно так же без крайностей. Интерфейсы, события, какой-то уровень абстрагирования нужен. Но я слишком часто сталкивался с просто переусложнённым кодом вообще непонятно зачем)
👍7🤔1
Одна из моих любимых фич за последние годы в Unity — это VFX Graph) С ней можно делать откровенную магию. Конечно, как и любой VFX она требует некоторой насмотренности. К VFX можно подходить по разному. Для придумывания каких-то новых эффектов нужно экспериментировать и иметь некоторое художественное понимание. С другой стороны для повтора чего-то существующего достаточно просто пытаться технически разбирать "из чего состоит тот или иной эффект или явление". Но для начала я в любом случае советую изучить инструментарий и пройти как можно больше туториалов) Это всегда отличный источник идей и "набивки руки" :) Вчера я наткнулся на неплохой туториал по созданию портала через VFX граф :) https://www.youtube.com/watch?v=V2NZb0WN7SY
Шейдер граф

Я очень любил писать шейдеры кодом. На мой взгляд это было быстрее) Ну и с реймаршингом и т.п., это правда так (ставь 🔥 если стоит написать про реймаршинг — не байт ни разу) Но сейчас я прихожу к тому, что графами в разы проще делать сложные эффекты. Когда тебе не приходится в 100 раз искать по куче проектов тот же дисторшн. Или же просто нужно "покрутить" и "по переставлять". Добавить френеля, убрать френеля, пошумить и т.п. Но возможно я так сильно не любил это всё дело, так как просто не знал про этот мануал и эту часть пакета шейдер графа https://docs.unity3d.com/Packages/com.unity.shadergraph@6.7/manual/Custom-Function-Node.html

Создавая свои кастомные ноды можно делать много прикольных авторских шейдеров. При этом воспринимать это всё дело часто в разы проще, чем векторный код + интересные шейдеры можно выложить скриншотом. Хотя конечно вот тут — код копипастить удобнее :)
🔥11
Работа с функциями в шейдерах

Я часто говорю, что программирование — это не математика. И это на самом деле так. Кроме шейдеров. Шейдеры — это математика. Дисторшн и т.п. сейчас художники используют во всю. Но первоначально это математика. У меня есть старая серия статей про математику) И в одной статье из серии я разбираю полностью уравнение плоской волны https://habr.com/ru/post/435828/ И в целом существует много прикольной математики) Из старых мат моделей, что я находил на просторах интернета я помню https://andrewhungblog.wordpress.com/2018/04/29/page-curl-shader-breakdown/ Идея её проста, по сути "накручивание меша на цилиндр" :)

Но чем интересна статья про волны, она отлично иллюстрирует, зачем часто бывает полезна удобная визуализация. И если в самой статье я рекомендовал вольфрам, то позже я нашёл инструмент в разы удобнее) https://www.desmos.com/calculator?lang=ru Да, конечно диффур там не посчитаешь и т.п. Но для того, чтобы подобрать правильный параметр для синуса или какую-то кусочную функцию — подходит отлично. И в разы проще разобраться, чем в том же вольфраме :)
Очень жаль, что Brackeys год назад перестали вести свой канал. Конечно не скажу, что я согласен со всеми их туториалами (портал между локациями я бы делал через стенсил, а не через две камеры, как пример) Но всё равно там много крутого контента. И советую с ним ознакомиться, если вдруг не знали :) Ну и этот туториал диззолва тоже неплох https://www.youtube.com/watch?v=taMp1g1pBeE :)
🔥6
Паттерн Декоратор

Думаю это самый популярный шаблон проектирования. Многие языки целиком пронизаны им. JS в особенности, где по сути "всё декоратор". Определение и пример формальные почитать можно тут https://metanit.com/sharp/patterns/4.1.php, хотя я не согласен с определением Component. Так как по тексту статьи Component должен быть интерфейсом, а не абстрактным классом. Но мы же говорим про Unity. В юнити декоратором по сути является любой MonoBehavior, так как он расширяет функции объекта, и в любой момент эти функции можно снять или отключить :) Но это даже не самое главное. Тоже самое условно можно сделать через наследование) Декоратор как раз таки прикол в том, что по своей структуре позволяет избежать сложной иерархии наследования)

Например вы хотите, чтобы у вас в игре был меч. И чтобы он бил "огнём", "ядом" и "льдом". Как это можно сделать?

Ну самый упоротый путь сделать класс Sword, и от него отнаследовать ToxicSword, FireSword и FrostSword. Это позволяет сохранить разное поведение, но усложняет реализацию комбинированного урона

Можно сделать "маску урона". По сути завести enum DamageType и хранить в мече либо битмаской, либо словарём (если значения урона разные). Поведение будет определять класс меч, а урон резолвить переданный в него словарь. Это лучше, но тоже не так удобно

А можно сделать компоненты, которые определяют тип урона FrostDamageModificator, ToxicDamageModificator и FireDamageModificator. Которые добавляют классу меча функциональность урона. Так же какой-нить AOEAttackTypeModificator и т.п. для того, чтобы определить как меч бьёт. И потом собрав все эти компоненты по конфигу айтема меч получит все нужные ему свойства. А класс Sword будет просто скелетом определяющим, как это всё между собой дружить :)

И это один пример. Я допустим очень сильно люблю декорировать всякое в маркерном AR всякие эффекты. Конечно с мечом пример долго реализуем, поэтому в репозитории я привёл более простой пример с декорированием инпута. Его в целом можно сделать и без общего класса скелета, он сделан скорее для наглядности :) https://github.com/Nox7atra/PatternsUnityPlayground

Да, хитрая иллюзия того, что в юнити скелет не знает про свой декоратор. Но важно понимать, что в юнити скелетом является трансформ, который через дженерик метод добавляет на себя компоненты наследники MonoBehavior. Так что это нормально, чтобы класс "скелет" знал про декораторы и наоборот. Хотя там зависимости опять таки можно развозить кучей способов. Основное это всегда функциональная суть паттерна)

Суть паттерна Декоратор:
1. Расширение функционала без наследования
2. Возможность натянуть на скелет (основное что непонятно новичкам в этом паттерне — это его блок схемы. Даже в примере по ссылке выше — это лишь один из примеров реализации такого скелета)

Основные плюсы:
1. Легко включать выключать различные функции и придавать свойства объекту
2. Легко комбинировать между собой свойства, при этом зная другие паттерны делать это так, чтобы декораторы друг о друге ничего не знали (что вернее)

Прошлые разборы:
1. Команда — https://news.1rj.ru/str/dyadichenkoga/76

P.S. Когда соберу большую часть паттернов, надо будет закрепить наверное на канале в какую-нить общую статью :)
👍51🤯1