Заказал УЖАСНЫЙ код у фрилансера за 500 рублей. Unity + C# рефакторинг
Вставка
- Опубліковано 18 тра 2024
- Сидел, никого не трогал и заказал код у фрилансера за 500 рублей час. Знатно офигев от результатов решил переписать его во что-то более вменяемое. :)
Обучение с нуля с гарантией трудоустройства - ijunior.ru/unity-start?...
МОЯ КНИГА - csharpbook.sakutin.ru
Я В VK - rsakutin
ЯЮниор:
Группа - holymonkey_sandbox
Канал с уроками - / @user-wq2dk1kn2v
ЧАТ В ТЕЛЕГЕ - t.me/csharp_faggots_fan_club
Discord - / discord
INSTA - / sakutinhuytin
00:00 - Введение
02:40 - Обзор решения
07:22 - Рефакторинг класса Cube
14:13 - Рефакторинг CubeManager
30:43 - Играемся с методами расширения
В видео намётки по рефакторингу, после 2000 лайков выпущу отдельный видос где уже более комплексно пройдёмся по коду и решим многие проблемы на корню.
Также при записи я совершил пару ошибок, предлагаю внимательным их все найти
Дистанция считается от одного и того же объекта
to может быть null
where вынести из цикла дабы не создавать коллекции при каждой итерации
Забыл поменять 0.1f на _speed
Кстати, ты видел видео у S0ER`a, где он разбирает почему предусловия на валидность это плохо
Что скажешь?
ua-cam.com/video/5Od1VaDL090/v-deo.html
@@user-cx1vt1kp1j У него другая ситуация, в его примере предусловия не приводят к ошибке. В моём случае предусловия уточняют ошибку. Т.е у него с предусловием будет мусор на выходе (undefined) а без будет явная ошибка. У нас же и так и так будет ошибка, только с предусловием мы можем точно сказать что пошло не так.
@@rsakutin предусловия хороши для создания фреймворков и утилит, но для сквозной логики, да еще и в циклах - это смерть производительности
Однажды Билла Гейтса спросили как ему удалось достичь таких успехов в программировании операционных систем на что он ответил:
Если код работает, значит не надо его трогать
жиза
Я просто хотел посмотреть как дерутся кубики :(
я время от времени захожу, но кубики до сих пор не дерутся. Меня это несколько расстраивает.
Брат, все будет хорошо, ты не один такой!!!
@@DarkW1zard Я тоже ждал
Пацаны! У Романа хороший и честный курс!!! Я прошел его и меня устроили на работу, я мою полы у них в офисе, всем советую, полов на всех хватит)
за 54000 рублей в месяц?
Тебе повезло, я унитазы чищу 😥
@@dimonser7663 ну и хули ты ноешь, я вообще пылинки сметаю
@@Disappeared... тебе больше повезло, пылинки не все в говне
Блин, эта ниша уже занята, я опоздал... 😢
я думаю перфоманс просел в разы, столько замыканий с переборами в замыканиях с переборами с linq да еще и в апдейте, что ну его нафиг )
в TransformExtensions в 29-30 строке ошибка (нарушена логика, поломан код)
и лучше завести переменную для closestDistance что бы её каждый раз не пересчитывать
конечно смотрится эстетически красиво, но между говнокодом вначале и перегибом получившимся в результате где-то лежит истина
Ура. Вот сейчас честно. Если бы все последние ролики были бы такими, критика - объяснение - показал решение, претензий бы не было. И сейчас их(претензий) нет. Адекватно.
Джва года ждал подобный разбор, если не больше. Спасибо! Давай ещё.
Видео просто супер, намного лучше когда рефакторишь в прямом эфире, думаю со мной согласятся...
Лучше как раз так. Стримы обычно нудные и растянутые выходят
Очень интересно наблюдать, как у него в цикле сочетается три условия с разной стилистикой, это шикарно)
Мое перфекто выдавило мне глаза после того как Роман так и не применил поле _speed с магическим числом 0.1f в классе cube. Это как минимум попахивает дилдом в глаз
Спасибо, что ты есть!
Благодаря тебе начал копать документации по неймингу и стилистике кода
Кстати, почему бы не выкладывать заранее какой-нибудь код и предлагать подписчикам его отрефакторить, а потом их закидывать говном (ну или говорить, что они молодцы)? А?
Во-первых, я бы прикопалась к твоей оценке денег фрилансеров. В отличии от офисных работяг, они также занимаются поиском заказов
Во-вторых, если есть конкретная КОНЕЧНАЯ цель, то в чём смысл тратить время на качественный код и расширяемость? Если дальше над ним работать не нужно, то расширяемость не имеет смысла, за которую ты очень сильно цепляешься
В третьих, я, как и многие другие люди, ждала, что хотя бы продемонстрируется работа этого кода, но хрен там плавал
В четвёртых, многие комментаторы жалуются на ошибки в коде, и это выглядит вдвойне нелепо, что "плохой" код работает, в отличии от "хорошего"
В пятых, нафига в методе TakeDamage было кидать исключение, если значение полученного урона меньше нуля? Почему бы не написать просто return? Это в юнити считается нормальной практикой, или во всём шарпе? Исключения - это отличный способ ловить серьёзные ошибки, но... тут же её нет. К тому же, если и происходит какая-то такая ситуация, то ловить её нужно здесь и сейчас, а не где-то извне
Это вроде от взлома было сделано
Нельзя умалчивать ошибки. Если сделать просто return, то после вызова метода может ничего не происходить, и не будет ясно почему. Это используется как в Unity, так и в C# в целом.
А насчёт расширяемости, возможно заказчику нужно будет расширять этот код, так что он должен быть расширяемым по идее. Конечно 500 рублей возможно не так уж и много, однако даже за такие деньги код не должен быть настолько плохим.
@@glazyrik6923 Нет, это просто принципы хорошего кода.
Полностью согласен
@@ram-1919 ну чет ты переоцениваешь важность ошибки при TakeDamage меньше нуля. Если делать хилки то один хрен код в видео придется частично переделать
Я взял заказ на бирже , нужно было спарсить сайт.За 500руб, я написал код,парсил сутки,оказалось спарсились около 60%товаров,не понял что за дела,но потом оказывается на сайте верстка разных блоков отличается.Решил парсить по категориям, написал код под каждую из различий верстки,парсер работал оочень медленно, и нужно было чтобы ПК наверное 3 суток работал без перерывно,чтобы спарсить сайт.В итоге через часов 5 подумал "зачем оно мне надо за 3000р(заказчик предложил поднять цену)", и слился.
Андрей 17 лет.
Не ну кнш Linq в Update это жестко.
У меня аж глаз задергался)
как то начинал изучать c# забросил и через время пересел на Java и не могу найти канал похожий на твой ,очень все информативно , хорошо хоть языки похожие и можно все равно что то для себя подметить)))))
На мой взгляд, подобные ролики это лучшая реклама ваших курсов. Наглядно видно чему можно научиться и как у вас пишут.
37:39 в коде четверное перечисление IEnumerable это не очень хорошо, т.к. IEnumerable не означает, что его несколько раз можно перечислить. :)
Такой контракт либо явно через IList надо задавать, либо проверочки как-то по другому делать...
А в коде метода достаточно дернуть `source.Min(x => Vector3.Distance(x.position, to.Position))` вместо цикла.
Если уж одно перечисление хочется оставить, то там и эксепшны все нужные выпадут. Останется проверить если result == to => throw InvalidOperationException()
(В теле тоже, кстати, опечатка, в коде сравнивается another и another)
source.Min круто выглядит будет, из головы что-то вылетело совсем :)
37:58 Неявная зависимость на то, что Where проверяется в ходе цикла.
Если мы берем первый куб, ставим ему второй в противники, то мы пропускаем второй куб только потому, что там Where проверяет внутри себя по очереди элементы, а не сразу возвращает отфильтрованную коллекцию.
Считаю это не очень очевидным решением
@@emptysoul438 ничоси ты шаришь, будь моим наставником!
@@emptysoul438 Кстати не знал, что where отсекает на ходу. Думал по приоритетности задач, сначала отработает linq и создаст новую коллекцию, а потом уже цикл по ней будет спокойно работать по. Ну, теперь буду знать, что это не так.)
Хотя, догадывался об этом, когда читал конвенцию. Там вообще написано, что рекомендуется подобные действия с linq перед массивом выносить в отдельную переменную (разумеется с var) и писать в полной форсп. Мол, если пихать всякие цепочки прямо в цикл, то это не очевидно и когда цепочки длинные не читаемо.)
А как понял лучше писать примерно так:
var orher = (from cube in cubs where cube.enemy is null select cube);
//или
var other = cubs.Where(cube => cube is null);
foreach(Cube cube in other)
{
...
}
@@emptysoul438 не совсем понял о чём ты говоришь, в плане поведения ничего не изменится хоть ты сразу-же отфильтруешь или передашь в closest итератор where, в любом случае роман внутри closest идёт форичём по сурсу, соответсвенно он итерирует WhereIterator который нам вернёт уже элементы которые прошли по кондишину который в него передали, даже если бы Роман реализовал свой экстеншн по паттерну итератор (как в LINQ), то всё-равно кондишин романа в closest исполнялся только в том случае, если кондишн по текущему элементу в where вернёт true. Так что решение вполне очевидное, никаких проблем не вижу с точки зрения дизайна или поведения.
Вот такого побольше, Ром) Это и полезно, и рожать ты можешь такого контента много, и сразу видно, к кому учиться надо идти)
ага, убрал геткомпонент в другой класс и вызывается он из апдейта в цикле
А какова была точная формулировка задачи для фрилансера? Если чтобы работало, то задача выполнена :) Я как-то оооочень давно на 1-м курсе писал софтинку для анализа геометрии GPS-карт для работы. Сейчас я в ужасе от написанного мной тогда кода, однако софтина работает и используется уже 13 лет и никто не жалуется, т.к. она закончена и расширение и развитие её не планировалось изначально. имхо расширяемость и поддерживаемость КОДА должны быть в постановке задачи, иначе тратить время на соблюдение всех принципов ООП просто незачем.
Тратить время? Зачем его тратить если все должно быть и так на автомате чтобы писать код правильно и умно а не написывать лишних строк так еще и непонятных... Имею ввиду под непонятные строки те что не понятны первое время а код должен читаться легко
@@owattara160 На автомате? Ты думаешь все сразу сеньорами после написания Hello World становятся? Есть задача, новичок может ее решить, точно так как описано в ТЗ. В чем проблема? Было бы написано нужна расширяемость и поддерживаемость, новичок бы за такое не взялся, если не умеет. А если бы взялся и не выполнил, тогда уже другой разговор. Для каждой задачи свои уровни навыков. Если вы ждете со старта сеньоров, которые идеально все знают и пишут идеальный код, то будет как минимум нехватка специалистов. Будет условно 500 задротов душных до чистоты, оптимизации и т.д. кода на всю Россию работать.
Я думаю, что использовать LINQ в Unity должно быть запрещено. Потом всё равно придётся их выпиливать из-за бесконечных стартеров из-за GC. В идеале код вообще не должен выделять памяти в основном цикле, только на загрузке. Ну и то что дистанция вычисляется не квадратом длины и не кэшируется для самого близкого - кровь из глаз.
Рекомендую глянуть Tools, Tricks and Technologies for Reaching Stutter Free 60 FPS in INSIDE, чтобы разучится использовать foreach, linq, list и прочее.
@@jkot20 А List чем не угодил?
Ну, не соглашусь. Если ты за это заплатил 500 рублей, значит человек справился с задачей за час. Более того, ты заказал код на фрилансе, что само собой намекает на то, что проект не долгоиграющий, его нужно сделать и забыть (например, для курсача в универе). Тогда какой смысл думать о рефакторинге и тд? В этом смысла нет.
Чел реально годно справился с задачей по соотношению цена/качества. Он написал код, который кое-как, но работает, протестировал всё это дело. И справился с этим за час. У тебя пусть и с объяснениями ушло минут 40 только лишь на рефакторинг. А теперь посчитай, за сколько бы ты сделал задачу с нуля. Ушло бы часа 2-3. Теперь давай подумаем, стоит ли эта задача 3 часов? Если она прямолинейна, о масштабируемости говорить не приходиться? Нет, не стоит.
Я конечно не знаю, может, что в задаче было написано, но вряд ли: "Нужно сделать задачу с расчётом на то, что это долгоиграющий проект, его будут дорабатывать другие люди, сделай качественно, можешь хоть несколько часов это делать, не торопись."
Вот такой формат лучше всего! Кто-то написал криво и хрен с ним - нечего его хейтить... А ты показал как надо писать и объяснил почему да как... Вот за такое не лень Любо ставить
Еще вопрос, можно ли было вместо event Action использовать event Func, для того, чтобы сигнатура подходила под метод Remove? Там же возвращаемое значение имеет тип bool.
Роман)) не знаю куда еще написать, но можно ли у вас попросить демо доступ или подробное описание вашего курса?)
Можно ли в приложение добавить ролик с Ютюб или др.видеоресурса? Не прилетит после публикации своего софта в плеймаркет бан за автор.права роликов?
Очень классно разобрал и собрал код)) Жду следующего ролика
Кулдаун не имеет смысла устанавливать в редакторе, так как после первого же обнуления он приравнивается 1. Не надо путать сам счётчик с его верхней границей. Нужна отдельная переменная.
Боже, хоть кто то заметил, я думал я один такой
На кого ваш курс рассчитан? На нулей, начинающих?
Сакутин, давай несколько строчек кода с твоей игры, как это в процессе выглядит
36:00 метод Transform Closest
1. почему сначала поиск element == to, а следующей проверкой уже Count() == 0? Разве не логичнее наоборот, если в списке ничего нет то и элементов там не будет
2. почему не использовать вместо x.Count() == 0 !x.Any() ?
Спасибо за разбор
У меня вопрос. Я LINQ не пользуюсь в Unity. И вот, такое количество запросов в update не будет генерировать кучу мусора?
Они не в Update фактически, они выполняются для свободных кубов. Но то что код так грубо размещён в Update - это проблема которая создаёт такую путаницу
@@rsakutin понял, спасибо за ответ!
бедняга, как ты без линки со списками разбираешься?
Может уже писали, а в методе Closest если мы нашли элемент, не лучше break ставить, что бы остановить перебор обьектов??
Уже не помню всего кода, но суть в том, что ближайшим кубом может оказаться и последний из списка.
Поэтому break здесь использовать не имеет смысла.
Менеджер кубов в апдейте не нуждается, тут надо сигналами работать. Если куб свободен, пусть посылает сигнал и вызывает поиск врага. Если куб сдох, пусть посылает сигнал, чтобы его могли удалить из списка. Нечего там апдейту делать.
Классный выпуск, спасибо!
вообще что то жестко, вот у нас есть список Кубов а что будет если другие кубы убьют пару кубов из этого списка, пока мы убиваем куб? Там будут указатели на null, или как это будет работать, или мы получим доступ к неправильной области памяти? Метод дестрой при уничтожении куба он наверно переведет его в другое состояние, но поскольку есть ссылка на объект, он не будет удален сборщиком мусора?
Не совсем понял для чего использовался IEnumerable в параметре метода FindClosest... Чтобы List с кубами протащить? А почему просто List в параметре не прописать? (вопрос от нуба, если что... камнями прошу не забрасывать).
Как говорил кто-то умный "ты не работаешь плохо, потому что тебе мало платят, а тебе мало платят, потому что ты работаешь плохо"
пиздеж, никто не будет платить дохуя просто за то что ты хорошо работаешь, можешь усраться ,но пока ты напрямую не скажешь - либо вы повышаете зарплату, либо я ухожу - никто тебе ничего не повысит
Ну, скажем так, твоя трудоспособность и трудолюбие подсознательно кореллируют с твоей самооценкой и твоими амбициями.
Если тебе или лень или сложна в "нормально делай - нормально будет" то и "доминируй, двигай тазом" тоже будет сложно и ты подсознательно согласишься с "да я говно, посему я готов работать за три копейки".
Я думаю из-за того, что ты не захотел в этом видео разделять сущности, реализация CubeManager стала слишком мудрёной. Пока ты не начал добавлять методы расширения код и вправду стал очень понятным. Дальше мне кажется замудрил немного. Но Формат видео очень нравится. Жду выпуска про Бугаенко, очень интересно узнать твое мнение о нем.
Спойлер:
чувак переделал говнокод в еще больший говнокод с претензией на правильность
Роман, вроде вы говорили что "мы никогда не используем статистические методы или классы" ?
Или я что то не понимаю?
В 360 код афигено видно
13:47 я б еще else if сделал одной инструкцией, не выделяя блок else и if отдельно, раз у if нет парного else, но тут уже на вкус и цвет, может показаться, что в одну инструкцию будет чуть менее читабельно и понятно, хоть и чуть короче и красивее визуально
А можно было просто вместо cooldownAttack сохранять время предыдущей атаки, а когда атакуем проверять, last - Time.deltaTime > 1, если это верно, то в last записать текущее deltaTime и атаковать?
почему Вы не добавили в первом коде методы сеттеры начального состояния переменных?
Ошибка копипасты в 29-30 строчке в методе поиска ближайшего.
Можно было бы еще запоминать дальность от прошлого в переменную и с ней сравнивать. А еще квадрат магнитуды использовать вместо дистанции если хочется еще ускорить код )
Еще не уверен не будет ли просчитан куб у которого уже появился враг? мы выдаем текущему пустому кубу врага, и врагу говорим что мые го теперь враг. Но этот куб же дальше будет в листе свободных кубов в этом апдейте нет? Да и первый тоже останется. их по сути мне кажется удалять надо из листа заменив форич на фор.
Еще ошибка в кубе была. Просто переменную недопереименов кое-где
Самый лучший ролик на канале
я не фрилансер, работаю на себя, но даже я лучше бы написал за спасибо😐, может поэтому я ничего не зарабатываю
Подскажите: как правильно получить все нужные объекты на сцене(как например в видео - получить список всех кубов)
Можешь создать ивент в старте по типу "я появился", а кто-то там уже его может обрабатывать. Или можешь производить инстанс обьекта вместе с добавлением в лист (главное после разрушения не забывай удалять). Ну или другие способы
Похоже джун не реализовался и открыл свой канал на ютубе)) Ты ТЗ выдал тебе на писали под твой ТЗ код, что не так?
Посмотрел 15 минут, ожидая увидеть какой-то реально криповый код уровня самых тайных и закрытых индийских школ кодинга. А увидел просто обычный код, который РАБОТАЕТ, и ЧСВ-шного школьника, который кукарекает. Было ли в ТЗ написано про стиль кода? Публичные поля ему не нравятся? Смешно видеть начинавшихся книжек про ООП и клин код и считающий, что это негласный стандарт языка. Хотя сам язык почему-то ничего не запрещает. Что уж говорить про то, что в шарп иногда залазят ребята из С, и пишут так, чтобы перформанс был, потому что это требуется. Самое глупое в видео - это попытка пересчитать заработок фрилансера за час кодинга на месячную зп. В офисе у тебя зп постоянно капает, работаешь ты или нет. А фрилансер большую часть времени заказы ищет.
чел, ты прав насчёт цены и стиля, который с исполнителем не обсуждался. Но например публичные поля это не просто до#б, это прямая уязвимость кода. Если не любишь ООП и его правила, то не юзай языки ООП, пиши на Си, радуйся жизни.
Фрилансеры потому и проводят бОльшую часть жизни в поисках заказов, потому что у очередного заказчика первый заказ становится последним, как раз потому что гуру фрилансер не делает анализа своих ошибок.
Можно конечно вести демагогию а имел ли он право делать видос из чужой работы и выставлять исполнителя дураком, но он бесплатно сделал ему ревью, которое, если фрилансер допетрит мотать на ус, сделает его ценник не 500 а 1500.
@@MaruskaStarshaya а в чем будет заключаться уязвимость кода?
@_dikiy_omlet_102 публичные поля могут все изменять и можно будет легко сделать подмену значений
@@TherryYT а понял, спасибо
ManagerManager - ведь должен же кто-то контролировать этих менеджеров.
А почему Update private? Может не досмотрел где он используется в классе Cube?
"У мастера хороший код - единственный стиль", - японский Сенсей Аригоша Харидударь
Роман, как вам идея просто показать скорость времени компиляции кода фрилансера и вашего? Заранее спасибо
а какая разница сколько код компилируется?
@@reosfire возможно он имел ввиду перфоманс
я бы тоже хотел бы взглянуть на графики профайлера
Я, будучи питонистом, немного обескуражен таким количеством вложенных итераторов, изменением размерности списка внутри цикла по нему, а так же наличием такого большого кол-ва повторяющихся проверок. будь этот скрипт написан на питоне, и в игре было бы 5 FPS от силы. Ну всё же я понимаю, что NNS - это вообще отдельная тема для разговора.
Ну c# явно быстрее питона, поэтому такое он может себе позволить)
Вы хотели мерседес по цене оки. Сколько платите то и получаете. 😁
По сравнению с предыдущими видосами этот на голову выше, т.к. видны рассуждения, которые приводят к хорошему коду
а что ты ожидал от кода за 500 рублей?
Философские рассуждения, какой бы ещё паттерн из ООП засунуть в этот кусочек кода
Почему не включишь режим вима? Очень много работаешь мышкой, это все можно ускорить
Попахивает exception-ом при итерировании когда удалится элемент из _cubes. Подстройки перед вызовом функции под код внутри функции - печально. Постоянно дергать linq - печально.
отличный формат
зачем нижнее подчеркивания в названии переменных?
16:10 - почему паблик, почему не геттер и сеттер?
=> в Юнити не работает, это оператор Линк.
Nearby - читается "ниа-бай", а не "нёби"
Походу если после метода старт добавятся кубы на сцене, то старые кубы не будут их быть( А метод старт я так понял при инициализации объекта происходит
Код должен быстро и правильно работать. А с названиями переменных всем не угодишь)
А может на 19:48 вместо Contains сделать !cube.HasEnemy? Ведь в another будут свободные кубы и если cube.HasEnemy будет false то это значит, что он находится в another.
Не проще вообще цикл foreach изменить таким образом:
...
if(!cube.HasEnemy)
throw new InvalidOperationException();
var nearby = others.First();
float minDistance = Vector3.Distance(cube.transfrom.position, nearby.transform.position);
foreach(var another in others) {
float distance = Vector3.Distance(cube.transfrom.position, another.transform.position);
if(distance < minDistance) {
nearby = another;
minDistance = distance;
}
}
...
minDistance можно инициализировать максимальным значением float или бесконечностью (вроде в C# есть такое понятие). Вроде выглядит намного лучше, тем более если инициализировать minDistance по другому. Хотя мне не самому не нравится cube.transform.position и т.д.
Так же метод findClosest является private и мы передаем в него IEnumerable без самого cube, но внутри проверяем чтобы его не было, для чего делается эта проверка? Мы же знаем, что передаем без cube. Это просто для себя?
И я заметил, что часто используют Linq, и хотел спросить, а это не долго? Ну вот в коде используется Linq, чтобы убрать сам куб из списка свободных, не проще в foreach просто пропускать его?
P.s. я C# учил несколько лет назад, и на нем уже давно ничего не писал, а с Unity ни разу не работал. И да писал в блокноте, скорей всего есть ошибки в коде, не стал вглядываться
Count() == 0, у тебя цикл по всей коллекции будет, лучше Any () == false
Почему ты "служебные" методы поместил вначало а не в конец класса? По значимости они нулевые, когда файл открываешь каждый раз мотать вниз?
Closest всегда возвращает первый элемент списка, но это уже другая история KEKW
Aha, Classic.
Рефакторим код, делая из рабочего говна нерабочую конфетку.
KD-tree напрашивается для поиска ближайшего объекта
Всем привет!
Надеюсь, что тут есть знатоки, кто сможет подсказать: Какой конкретно вид платформера следующие игры - castle crashers, tmnt rescue palooza и т.д.
Вопрос конкретно в том, что это вроде как 2D платформер, но с возможностью вертикального перемещения или я совсем неправ?
Хочу попробовать игру создать такого типа, буду очень благодарен.
Мечтаю, чтобы Рома купил код у меня да ещё и ошибки разобрал
Deep dark fantasy
предлагаю запретить if/for/while без фигурных скобок на законадательном уровне!
Вам python перейти языкe С блоки необходимы.
А тебя не смущает в методе расширения GetComponent вызываемый каждый кадр? Он насколько я знаю работает не так уж и быстро
Не каждый
У меня блин стилистика кода хорошая я знаю как делать не нужно, но я просто не могу программировать, я не знаю, что писать
надо сначала на отъебись делать, а потом рефакторить, или на карйний случай переписывать. По началу можно писать только быстро ИЛИ качественно.
Смотри другие каналы)
Кучу туториалов выполни и тогда придёт опыт. Ну свою стилистику и знания применяй.
Знать и уметь - это вообще разное.
Ты хотел типу var присвоить null? :)
Ну я понимаю, что сравнение нахождение дистанции между самим собой и проверка на то когда же она станет меньше самой себя это опечатка. Но блин. Называть метод Closest (где глагол?), запихивать в него геткомпонент и вызывать в апдейте это конечно мощно
@@PurpleDaemon_ до конца досмотри
@@PurpleDaemon_ еще кстати момент заметил. Он вызывает First(). По идее если число кубов будет нечетным, то последний куб, который будет искать себе пару вызовет First() для пустой коллекции (так как сам куб исключается) и вылетит эксепшн. Т.е. он отрефакторил по большей части все красивенько, но код теперь не работает
@@PurpleDaemon_ ну так он нагородил кучу исключений в методе расширения, чтобы потом еще проверки делать в апдейте? В результате рефакторинга все равно код как бы рабочий должен быть. Ну и здесь тесты как по мне излишни, да было бы лучше с ними, если это подразумевается как модуль для большой игры (Рома вроде что-то такое говорил), но на деле это как модуль не выглядит и близко
@@PurpleDaemon_ Наверное надо не забывать про 500 рублей в час. Если только "структурный рефакторинг" занял 30 минут, добавить сюда "сначала тесты писать", и получится, что решение задачи займет ..ну, допустим, час (конечно в "правильном" ее исполнении - как ожидалось за 500 рублей в час). Т.е. исполнитель оценивается в 8 * 500 * 20 = 80 тыс.рублей в месяц примерно (в наилучшем случае). ...не забываем еще вычесть налоги отсюда и, конечно, другие обязательные платежи :) .. т.е. в среднем выйдет где-то в районе 77 тыс в месяц. ...ну.. это в лучшем случае.. (когда ты по 8 часов 20 дней в месяц .. и 12 месяцев подряд)...
А так... конечно, если чисто для показать/посмотреть - всё очень красиво, правильно, весело, по-деловому и немного ошибок :)
Не лучше было бы в Cube поле с врагом заменить на рейкаст, а то выглядит очень странно?
Блин, это сильно повысит Аллоки, инициализации ексепшенов + линку которая тоже подбрасывает их.
Формат без говна намного приятнее, продолжай!
а почему только 360р?
37:37
if(Vector3.Distance(another.position, another.position) < Vector3.Distance(another.position, another.position)) - лолчто?
У Ромы все всегда компилируется!
Ой да госпади мелочи, там такой хуйни валом. От события уничтоженого куба он не отписывается, для магического числа 0.1 он создал поле, но 0.1 так и осталось и т.д. Забей, не обращай внимание 😁
@@EvilYarik ну вот зачем, и зачем ты потратил свое время?каков позитивный момент?
@@DT-hn3xq , Что позитивозависимые наркоманы забыли на канале Ромы 😂? Вы не найдёте сдесь дозы, вам тут нечего ловить! Сама идея канала в нулевой терпимости к коду 😈. А я напротив посоветовал на мелочи внимания не обращать 😇.
@@EvilYarik простите моя ошибка,на лету нераспознал контекст
Что такое фасадирование?)
1. в проверке расстояния поломал логику
2. ближайший куб из списка - как-то нелогично, лучше ближайший из списка к кубу (cube.Closest(others))
14:08 "мы к этому вернёмся после менеджера" - вернулся? я, честно, пока смотрел уже забыл
Ничерта непонятно, но очень интересно.
По-моему это уже код не на 500р в час, хотя не мне судить, я как раз пишу подобный говнокод как в начале...
Роман, хватит делать такие переходы. Смотреть невозможно, делай прямые склейки, так намного лучше
12:58 почему _attackDistance и _speed объявлены как переменные, если они нигде не меняются? Их нужно было объявлять как константы.
readonly тоже самое считай
Такой вопрос. Не то чтобы я гений c#, но меня немного смущает сначала отбор через select, а потом хождение по всем трансформам. Ну, конечно по сравнению с тем что было это вообще не проблема. Но все таки может кто-то обьяснить, так действительно правильно делать, или лучше проходить через 1 цикл используя сразу трансформ
Ну вообще не очень такое корректно со стороны оптимизации. Там много таких штук
А с другой стороны если не требуется очень сильная оптимизация то почему нет(кстати вопрос как это дойдет до байт кода, там возможно умные алгоритмы шарпа развернут это дело в один красивый цикл)
Юзайте райдер. Он автоматом почти все предложит перерефакторить, как Роман показал
За что заплатил, то получил! Почему-то никто это не учитывает. Программист оценивает свои знания и определяет лимиты при которых возьмётся за работу. Например если у меня нет опыта и я не знаю кучу тонкостей языка и механики работы "движка", то я могу предположить что могу сделать за 500 руб. Например если я имею большой опыт и знаю кучу тонкостей, то понимаю что здесь мне нужно проделать кучу работы и буду брать за эту же работу уже 10000 руб. Поэтому нечего удивляться, если эту стоимость предложил ты или программист, то надо предполагать что будет дерьмовый код.
Лайв гораздо понятнее😁
7:04 Update писать двойной for это уже грех, FindTag :(( fps 0.1
Скажите, почему public это плохо?
представь что твои органы стали public. это значит что в любой момент, без твоего ведома или разрешения у тебя могут что нибудь вырезать и не факт что что-то положат
Нарушение инкапсуляции, наверно
Почему Near - это ниар (нир), by - это бай, nearby - это нёби, а других ты за грамматику критикуешь?
Почему автор не отвечает на неудобные ему комментарии, где его объективно ловят на говнокоде? Я мидл разработчик. Но по его словам в других видео, где он докапывается до чистоты кода, оптимизации и всего такого, он сам все это нарушает. Говорит даже если просто пишешь код, чтобы показать в целях урока - пиши как продакшн реди и максимально чисто. Так яро сражается за правильный нейминг, а сам это правило нарушает. Ну да, зачем, он ведь просто в целях обучения, все равно это не надо будет расширять или поддерживать. Даже самое элементарное имя _speed. Так это скорость чего? Передвижения, атаки, восстановления хп, снижения хп? Кто говорил, что нужно писать полное имя, чтобы было понятно что это такое?
Ну по твоей логике speed можно понимать уже как угодно. Скорость, в большинстве случаев, по умолчанию используют в значении движения
Я вообще не врубаюсь зачем пытаться быстро печатать и ещё при этом делать ошибки. Можно же спокойно печатать код без спешки, когда ты собираешься что-то объяснять.
поставь себе райдер
Зачем я это смотрю, я же джавист...
Оооо да, 360p
да, только коддинг на 360 разбирать ну и графику можно
ничего не понятно, но что то понятно.