чувствовал себя "продвинутым" первые пять минут, а потом мозг поплыл. сложно, но познавательно. То, что понял, информацией было полезной, спасибо за видос
да во всех этих фичах (таски, корутины), под капотом жуткие городули, способные сожрать системные ресурсы и память. Так что лучше многопоточности и старых добрых простых условных ветвлений, пока что ничего не придумали... Так же можно программно в апдейт любой набор делегатов помещать - убирать... Ну и свой класс таймера сделать.
Не первый раз смотрю это видео, но если раньше это было просто под попкорн, и я тогда ничего так и не понял, то сейчас возникла именно необходимость в данном материале, и зашло на 10/10. Ни один из вопросов по асинкам не остался без ответа. Благодарю
Хз, в справочниках намного больше инфы. Но она вся вряд ли кому-то нужна, даже то, что здесь, не нужно большинству программистов Unity. Но стоит как минимум прочитать, чтобы иметь представление и все это не казалось магией в реальных примерах.
Очень круто и очень непонятно, ошибочно думал, что уже начал разбираться в C#.. Вы спустили маня с небес на Землю😀 Однозначно подписка и изучение контента, высший пилотаж!
Ничего не понял, но очень интересно)) Шутка) Материал подан очень хорошо! Спасибо большое! Давно хочу разобраться с async/await и думаю это видео мне очень сильно в этом поможет, буду точно его пересматривать ещё несколько раз.
очень недооцененный ролик - тема и ее разбор очень интересны! именно так и должно изучаться программирование - когда код разработчика осознаный! Спасибо большое - желаю роста каналу! лайк подписка)
Сама тема классная, да и голос что надо. Чего мне реально не хватает, это дельных примеров (желательно простоватых), где это конкретно стоило бы применить. А так, спасибо, очень познавательно.
Этот ролик про то, как работает изнутри, естественно он предполагает опыт использования тасок. В интернете куча примеров для новичков есть, в том числе рунете
Спасибо, полезно но сложновато -нужна практика, очень мало такого рода контента особенно на русском ютубе, очень интересно и полезно про всякого рода способы оптимизации, продолжай в том же духе))
Крутая инфа с точки зрения понятий устройства async await методов внутри, но так как канал ориентирован на разработку на Unity, я ожидал увидеть практичное применение этих самых async await, рассмотреть отличия async await от корутин и как можно заменить эти самые корутины. Машина состояния - одновременно интересно и не понятно) особенно не понятно, где это можно применять)
На базовом уровне там нечего применять, я хотел рассказать о внутренностях, так как это мало кто знает. Разработка на юнити ведется на шарпе и кто им не владеет хорошо - ничего не сможет сделать толкового
@@gaitavr1992 я возможно не совсем понял ответ, но я имел ввиду когда используют coroutine и в методе есть такой код: yield return new WaitForSeconds(time), зарание спасибо)
@@gaitavr1992 Насколько я понимаю, async включает в себя весь функционал корутины и привыкнув к нему можно от корутин отказаться. Так ли это? Или есть случаи где так просто замену провести не получится?
Хорошее видео, спасибо Однако Стоило рассказать как не нужно делать чтобы не получить дедлок А также, что цена этого всего удобства - аллокация памяти И если в обычном .нет вне юнити - это терпимо, то у юнити довольно печальный GC Поэтому что-то там поэвейтить в UI - это нормально, а вот создавать таски направо и налево в игровой логике - так себе идея
Очень интересно, хотелось бы спросить, а где можно найти все эти тонкости языка ? А то я прошелся по возможностям языка, но теперь интересно как оно устроено внутри, хочется узнать все тонкости и детали, может есть какая-то книга ? Или где вообще можно найти об этом ?
Очень мощно, недавно начал сам изучать эту тему, а тут удачно подъехал видос. Я правильно понимаю, что объяснение про машину состояний - это про то что под капотом у асинк-авейта и в целом можно и без знания этого им пользоваться? Просто в этом месте я понимание потерял. Upd. Из примера про кнопку понял что только с базовыми типами. Надо будет довкурить, чтобы делать камтомные авейтеры на все подряд.
Спасибо за видео! Запустил у себя ваш кастомный awaiter, но обнаружил, что второй await также срабатывает при повторном нажатии button1. Результат при этом выводит такой же, как и при последовательном нажатии button1 и button2. Почему так?
Максим, спасибо за видео. У меня вопрос: где выполняется таска, которую мы await'им. Вот у нас есть асинхронный метод, мы его вызываем, он выполняется до первого await, в await у нас таска, выполняющая длительную операцию. после await управление возвращается, основной поток не блокируется, и выполняет другие операции. Но где выполняется таска: в основном потоке параллельно (хотя насколько я помню, поток может выполнять только 1 задачу), в другом потоке, берется он из пула и т.д.? И как с этим всем связана машина состояний?
Await'ы, как я понял, лишь маркеры для компилятора, показывающие, как разбивать метод. Что будет, если между await'ами поставить goto? Например, {Label: await Task.Wait(1000); goto Label;} будет всего лишь бесконечный переход на состояние 1? Или такой подход может прям сломать async/await?
Спасибо большое за видео. Очень интересно если бы ты рассказал про многопоточность в юнити. Например как работают корутины, в одном потоке ли работает юнити и если да, то по какой очередности запускаются скрипты? Спасибо еще раз
Если есть таска t и у нее есть ContinueWith то нужно ли делать после ее создания await t - а то в видео говорится что авейтить целую конструкцию не получится(либо одно либо другое) но автор добавляет код "await t;"? Если авейт нужен то после него может быть еще код и другие авейты(которые отработают после ContinueWith?)? Если не нужен то как обработается ексепшн если он выбросится в ContinueWith?
Максим, что думаете по поводу последних двух абзацев(Avoid using async and await) из этой страницы документации Unity? docs.unity3d.com/Manual/overview-of-dot-net-in-unity.html Контекст синхронизации Unity всё равно заставляет работать всё в главном потоке и нужно использовать контекст по умолчанию или свой? Одинаково ли работает async/await в .NET и в Unity IL2CPP(на разных платформах, например UWP)?
Таски генерируют много мусора, что критично в узких горлышках(по ситуации смотрят). Если не указать какой синхронизационный контекст использовать, то все выполнится в том же потоке и проблем с unity типами не будет. А вот если эти типы не использовать, и не выполнять работу в том же контексте, то будет работать быстрее.
видел на каком-то буржуйском канале про стейт машину в асинк авейте, но там о билдерах/диспоузах ничё не говорили, как же хорошо что это всё под капотом и не надо гемороится. А кста разве оно не в IL код компилится, или вот тот С# код со свичами ты чисто для наглядности бахнул?
Здравствуйте, могли бы вы рассказать как можно сделать меню паузы с остановкой игры, но чтобы при этом анимация и Particle system работали нормально. Заранее спасибо. И большое спасибо за познавательный контент.
Это один из инструментов, требоваться может только в том случае, если команда повсеместно его использует. Но скажу сразу, что если проект не очень стеснен в производительности , то там будет или UniRX или Task
@@gaitavr1992 ну, я вот например знаю основы, то есть переменные, циклы, условия, массивы и так далее. Но при этом программировать на юнити я не могу, там же сишарп другой по идее
7й си шарп, вам нужно несколько вводных уроков пройти для начинающих, так как у меня контент ориентирован на повышение квалификации разработчиков junior +
Вижу, что ролик общеобучающий. В этой ситуации объяснять различие между асинхронным программированием и многопоточностью в начале неправильно. Это сбивает людей с толку. Разумно сосредоточится на самом механизме,принципе его работы, а само различие объяснить в конце. Тем более,что это различие не касается самого механизма. Я могу с помощью async-await запустить две параллельные задачи, которые будут выполняться на CPU и это не какой-то крайней случай, а вполне распространенная практика. Да и сам термин "асинхронность" но никак не связан с CPU, скорее он означает процессы, выполняющиеся независимо друг от друга. Поэтому, есть ли разница в какой среде происходит это выполнение (на разных устройствах или одном cpu)? На мой взгляд нет. Всё твердят как догму "асинхронность не равно многопоточность", а я скажу, что в ряде случаев равно 😅 И что, я буду не прав?
Нрмас. Я не ожидал описания того что происходит "внутри". Много "кривой" инфы у других авторов - иногда прям бесит. Запили видос про потоки! Как и когда использовать, ато у меня весь проект изначально на корутинах, а вот выделили время на рефактор, но я в Юнити не силён в потоках - очень не хочется "перемудрить".
Нахрен мне этот async, если я никак не могу с ним взаимодейстовавать с игрой? Ну для вычисление всяких формул пойдет, но мне надо нормальный многопоточность и с нормальным доступом с основным потоком. А то там все нельзя ничего взять присвоимть. Вообще ничего нельзя. Только вычисление координаты х и то как это возвращать - тайна века. Кароче много поточность в юнити сосет
@@gaitavr1992 я пытался генерировать коллайдер в реальном времени, изза этого в игре были фризы достаточно много кадров, что очень портило игру. Я хотел это в фоне обработать и передать в основной поток. Но как я понял, в юнити нету многопоточности с основным игровым потоком. Только эти координаты можно обработаьь и васё. А так тогда был излишне эмоционален, так как 1 месяц потратил на эту затею и не смог решить эту проблему.
Опять цвета одинаковые. Как это понимать. Если бы цвета значимых типов и ссылочных типов были разные, то тебе не пришлось бы объяснять, что AsyncVoidMethodBuilder это структура. Не подумай, что я придираюсь, я просто хочу сделать из твоих шикарных знаний в виде видеоуроков ещё и удобную интерпретацию для впитывания этих знаний.
чувствовал себя "продвинутым" первые пять минут, а потом мозг поплыл.
сложно, но познавательно. То, что понял, информацией было полезной, спасибо за видос
Имеет смысл вернуть потом и еще глянуть после некоторой практической работы
@@gaitavr1992 Я так поступал со всеми видео по паттернам. Спасибо за видосы))
До этого видоса даже не задумывался, что под капотом у async/await. Топчик, спасибо за видос !
да во всех этих фичах (таски, корутины), под капотом жуткие городули, способные сожрать системные ресурсы и память.
Так что лучше многопоточности и старых добрых простых условных ветвлений, пока что ничего не придумали...
Так же можно программно в апдейт любой набор делегатов помещать - убирать...
Ну и свой класс таймера сделать.
Круто, но сложна. Обязательно буду еще несколько раз пересматривать, может однажды все дойдет :)
дня 2 читаю про асинки, но это лучшее что я видел - и всего за 20 минут
Я бы рекомендовал на практике использовать хотя-бы пару раз, теория выветривается быстро
Спасибо.
И ещё четыре слова.
Читаю твои комменты, а в голове брутальный голос из видео)))
Спасибо, очень ценная информация, много чего узнал.
Хороший видос. Мощную работу проделал.
Не первый раз смотрю это видео, но если раньше это было просто под попкорн, и я тогда ничего так и не понял, то сейчас возникла именно необходимость в данном материале, и зашло на 10/10. Ни один из вопросов по асинкам не остался без ответа. Благодарю
Хз, в справочниках намного больше инфы. Но она вся вряд ли кому-то нужна, даже то, что здесь, не нужно большинству программистов Unity. Но стоит как минимум прочитать, чтобы иметь представление и все это не казалось магией в реальных примерах.
@@СветозарБоголюбов Подскажи такой справочник пожалуйста
круто! спасибо за видео. разобрался с асинхронными функциями!
Очень круто и очень непонятно, ошибочно думал, что уже начал разбираться в C#.. Вы спустили маня с небес на Землю😀 Однозначно подписка и изучение контента, высший пилотаж!
Ты невероятно полезен!
Понял где то половину, наверное....) Очень интересно, спасибо!
Когда понадобится свой эвейтер или случится странное поведение, то можно попробовать посмотреть еще раз)
Самый тематичный посыл подписаться в истории Ютуба)
Впервые вижу блогера с такой глубиной знаний, спасибо!
Хороший контент, буду ждать второй части!
Круто рассказал!
Ничего не понял, но очень интересно)) Шутка) Материал подан очень хорошо! Спасибо большое! Давно хочу разобраться с async/await и думаю это видео мне очень сильно в этом поможет, буду точно его пересматривать ещё несколько раз.
Спасибо за видео!
Я от Сакутина. Очень благодарен ему за рекламу и тебе за познавательное видео.
Я ему тоже благодарен, бустанул мне канал очень хорошо)
Видео огонь 🔥 Узнал много нового
Спасибо за отличное видео. Даже опытным разработчикам помогает освежить знания.
Очень доходчиво. Спасибо за вашу работу. Каждый раз очень жду нового видео.
Года 2 назад был бы такой видос, не было бы предела моей радости и задачу закрыл бы в срок xD
Очень хорошо рассказано
очень недооцененный ролик - тема и ее разбор очень интересны! именно так и должно изучаться программирование - когда код разработчика осознаный! Спасибо большое - желаю роста каналу! лайк подписка)
Круто, жду продолжения !
На эту же тему?
Спасибо, помогло в работе
Спасибо . Как всегда на уровне
Кайф. Спасибо!
Сама тема классная, да и голос что надо. Чего мне реально не хватает, это дельных примеров (желательно простоватых), где это конкретно стоило бы применить. А так, спасибо, очень познавательно.
Этот ролик про то, как работает изнутри, естественно он предполагает опыт использования тасок. В интернете куча примеров для новичков есть, в том числе рунете
просто отлично
Круто, Макс!
Я исполнил твою сихнронную операцию!
Отличное видео, спасибо.
Спасибо, полезно но сложновато -нужна практика, очень мало такого рода контента особенно на русском ютубе,
очень интересно и полезно про всякого рода способы оптимизации, продолжай в том же духе))
Крутая инфа с точки зрения понятий устройства async await методов внутри, но так как канал ориентирован на разработку на Unity, я ожидал увидеть практичное применение этих самых async await, рассмотреть отличия async await от корутин и как можно заменить эти самые корутины. Машина состояния - одновременно интересно и не понятно) особенно не понятно, где это можно применять)
На базовом уровне там нечего применять, я хотел рассказать о внутренностях, так как это мало кто знает. Разработка на юнити ведется на шарпе и кто им не владеет хорошо - ничего не сможет сделать толкового
И машину состояний сам никто не пишет, кроме кастомных эвейтеров. Зато знание принципа дает избежать различных проблем типа дедлока
Хех, помню времена когда TPL не было. Хорошо, что те времена уже в прошлом. Не то чтобы я такой старый, просто шарп начал ковырять еще в школе.
Годнота)
Спасибо
Круто, еще б примеры где лучше применять async, а где IEnumerator, спасибо.
Так это разные вещи в плане применения. Async нужен для асинхронного выполнения метода. Ienumerator это перебор коллекции
@@gaitavr1992 я возможно не совсем понял ответ, но я имел ввиду когда используют coroutine и в методе есть такой код: yield return new WaitForSeconds(time), зарание спасибо)
Ну корутина только с gameobject работает и всегда в одном потоке. Async работает везде и можно настроить потоки. Для легких вещей корутина ок
@@gaitavr1992 Насколько я понимаю, async включает в себя весь функционал корутины и привыкнув к нему можно от корутин отказаться. Так ли это? Или есть случаи где так просто замену провести не получится?
Корутина легче таски, иногда это критично. Плюс ожидание кадра и подобные юнити вещи заменить сложно
Cool) thanks
Было бы здорово в будущем увидеть уроки по UniRX сейчас на работе только их и используем
Хорошее видео, спасибо
Однако
Стоило рассказать как не нужно делать чтобы не получить дедлок
А также, что цена этого всего удобства - аллокация памяти
И если в обычном .нет вне юнити - это терпимо, то у юнити довольно печальный GC
Поэтому что-то там поэвейтить в UI - это нормально, а вот создавать таски направо и налево в игровой логике - так себе идея
Примеров дедлоков куча в интернете, я не хотел еще затягивать и без того сложное видео. А про выделение памяти все сказано
Такой чёрной магии я не видел с тех пор, как пытался писать шейдеры..
Очень интересно, хотелось бы спросить, а где можно найти все эти тонкости языка ? А то я прошелся по возможностям языка, но теперь интересно как оно устроено внутри, хочется узнать все тонкости и детали, может есть какая-то книга ? Или где вообще можно найти об этом ?
Очень мощно, недавно начал сам изучать эту тему, а тут удачно подъехал видос. Я правильно понимаю, что объяснение про машину состояний - это про то что под капотом у асинк-авейта и в целом можно и без знания этого им пользоваться? Просто в этом месте я понимание потерял. Upd. Из примера про кнопку понял что только с базовыми типами. Надо будет довкурить, чтобы делать камтомные авейтеры на все подряд.
Все верно, стейт машина+эвейтер+каркасный метод и будет работать без async await
@@gaitavr1992 спасибо
подскажи плис где можно почитать по подробнее по тому что ты показал?
Под WebGL это будет работать? У меня не получилось завести ((
хорошее видео, спасибо..можно сделать такое же, но про корутины ? как они под капотом работают и потом их сравнение с async/await
Как-нибудь дойдем
Спасибо за видео! Запустил у себя ваш кастомный awaiter, но обнаружил, что второй await также срабатывает при повторном нажатии button1. Результат при этом выводит такой же, как и при последовательном нажатии button1 и button2. Почему так?
Максим, спасибо за видео. У меня вопрос: где выполняется таска, которую мы await'им. Вот у нас есть асинхронный метод, мы его вызываем, он выполняется до первого await, в await у нас таска, выполняющая длительную операцию. после await управление возвращается, основной поток не блокируется, и выполняет другие операции. Но где выполняется таска: в основном потоке параллельно (хотя насколько я помню, поток может выполнять только 1 задачу), в другом потоке, берется он из пула и т.д.? И как с этим всем связана машина состояний?
Лучше еще раз посмотреть видео, особенно момент с самописными эвейтерами
А можно 1-2 примера, когда стоит все таки отправлять Task в отдельный поток?
Я делаю это при первой возможности, чтобы разгрузить главный и если я не работаю с юнити типами (gameobject, texture и тд)
@@gaitavr1992 спасибо
Await'ы, как я понял, лишь маркеры для компилятора, показывающие, как разбивать метод. Что будет, если между await'ами поставить goto? Например, {Label: await Task.Wait(1000); goto Label;} будет всего лишь бесконечный переход на состояние 1? Или такой подход может прям сломать async/await?
Мне такое никогда не пришлось бы попробовать. Я не использую goto в принципе, а вот в async/await он используется
@@gaitavr1992 а я все же проверил. Ничего не сломалось. Видимо, бесконечный переход на состояние 1
коментарий оставил. остальное сделал сразу перед видео, поэтому чтобы продолжить асинк или авейт?
Спасибо большое за видео. Очень интересно если бы ты рассказал про многопоточность в юнити. Например как работают корутины, в одном потоке ли работает юнити и если да, то по какой очередности запускаются скрипты? Спасибо еще раз
Судя по тому, что вы написали, присутствует сильная путаница. В рамках c# роликов сниму
Если есть таска t и у нее есть ContinueWith то нужно ли делать после ее создания await t - а то в видео говорится что авейтить целую конструкцию не получится(либо одно либо другое) но автор добавляет код "await t;"? Если авейт нужен то после него может быть еще код и другие авейты(которые отработают после ContinueWith?)? Если не нужен то как обработается ексепшн если он выбросится в ContinueWith?
Task.Yield() не до конца объяснил, в контексте Юнити это аналог yield return null для корутин
Круто. очень advanced, но увы весьма сложно для понимания. Кроме разных вариантов применения класса Task.
Good
Максим, что думаете по поводу последних двух абзацев(Avoid using async and await) из этой страницы документации Unity? docs.unity3d.com/Manual/overview-of-dot-net-in-unity.html Контекст синхронизации Unity всё равно заставляет работать всё в главном потоке и нужно использовать контекст по умолчанию или свой? Одинаково ли работает async/await в .NET и в Unity IL2CPP(на разных платформах, например UWP)?
Таски генерируют много мусора, что критично в узких горлышках(по ситуации смотрят). Если не указать какой синхронизационный контекст использовать, то все выполнится в том же потоке и проблем с unity типами не будет. А вот если эти типы не использовать, и не выполнять работу в том же контексте, то будет работать быстрее.
С uwp работал очень давно, когда еще таски не знал, сложно сказать. Ставлю на то, что будет работать
видел на каком-то буржуйском канале про стейт машину в асинк авейте, но там о билдерах/диспоузах ничё не говорили, как же хорошо что это всё под капотом и не надо гемороится. А кста разве оно не в IL код компилится, или вот тот С# код со свичами ты чисто для наглядности бахнул?
Это до IL кода, все await и async преобразуются в стейт машины и эвейтеры
жалко что у тебя перестали выходит видео (
Здравствуйте, могли бы вы рассказать как можно сделать меню паузы с остановкой игры, но чтобы при этом анимация и Particle system работали нормально. Заранее спасибо. И большое спасибо за познавательный контент.
есть ли способ килять все асинхронные процессы, запущенные в коде, при выходе из play mode в эдиторе?
Я бы cancellation token использовал. Также при рекомпиляции таски очистятся
а в юнити требуется использование тасков и асинхронных методов? Вроде же все решают курутины
Это один из инструментов, требоваться может только в том случае, если команда повсеместно его использует. Но скажу сразу, что если проект не очень стеснен в производительности , то там будет или UniRX или Task
А как вы смотрите на то, чтобы создать плейлист по сишарпу на юнити для людей, которые знают только основы обычного сишарпа?
Если человек знает обычный шарп - у него нет проблем в юнити с этим)
@@gaitavr1992 ну, я вот например знаю основы, то есть переменные, циклы, условия, массивы и так далее. Но при этом программировать на юнити я не могу, там же сишарп другой по идее
7й си шарп, вам нужно несколько вводных уроков пройти для начинающих, так как у меня контент ориентирован на повышение квалификации разработчиков junior +
На слух очень сложно понять, вот бы код посмотреть
бекгрануд в паверпоинте - юзал в универе на каких-то презентациях (((:
Вижу, что ролик общеобучающий. В этой ситуации объяснять различие между асинхронным программированием и многопоточностью в начале неправильно. Это сбивает людей с толку. Разумно сосредоточится на самом механизме,принципе его работы, а само различие объяснить в конце. Тем более,что это различие не касается самого механизма. Я могу с помощью async-await запустить две параллельные задачи, которые будут выполняться на CPU и это не какой-то крайней случай, а вполне распространенная практика. Да и сам термин "асинхронность" но никак не связан с CPU, скорее он означает процессы, выполняющиеся независимо друг от друга. Поэтому, есть ли разница в какой среде происходит это выполнение (на разных устройствах или одном cpu)? На мой взгляд нет. Всё твердят как догму "асинхронность не равно многопоточность", а я скажу, что в ряде случаев равно 😅 И что, я буду не прав?
Спасибо если можно и про
Про что?
@@gaitavr1992 походу он OperationCanceledException получил пока писал, а отправка сообщения уровнем выше стояла
Я понял что ничего не понял. Требуэ пересмотр.
Самое время написать что сложно с наскока понять.
Нрмас. Я не ожидал описания того что происходит "внутри". Много "кривой" инфы у других авторов - иногда прям бесит. Запили видос про потоки! Как и когда использовать, ато у меня весь проект изначально на корутинах, а вот выделили время на рефактор, но я в Юнити не силён в потоках - очень не хочется "перемудрить".
Дойдем и до потоков
когда узнаешь внутренности функций или какой либо логики в языке программирование, это пугает и ты отказываешься от использования этих возможностей :\
Не надо так)
Люди у вас тоже ошибка: async не поддерживается 2.3 версии
я думал асинк не работает с монобехами
Так и не была раскрыта явная разница между многопоточностью и асинхронностью. На том же metanit объясняется лучше
Инфа очень плотная, это видос не на один раз, несмотря на небольшой хронометраж.
Нахрен мне этот async, если я никак не могу с ним взаимодейстовавать с игрой? Ну для вычисление всяких формул пойдет, но мне надо нормальный многопоточность и с нормальным доступом с основным потоком. А то там все нельзя ничего взять присвоимть. Вообще ничего нельзя. Только вычисление координаты х и то как это возвращать - тайна века. Кароче много поточность в юнити сосет
Что за высер?
@@gaitavr1992 я пытался генерировать коллайдер в реальном времени, изза этого в игре были фризы достаточно много кадров, что очень портило игру. Я хотел это в фоне обработать и передать в основной поток. Но как я понял, в юнити нету многопоточности с основным игровым потоком. Только эти координаты можно обработаьь и васё. А так тогда был излишне эмоционален, так как 1 месяц потратил на эту затею и не смог решить эту проблему.
При объяснении не хватает примеров в играх... по этому полное непонимание
первые 5 минут понятно, потом ересь какая-то
Опять цвета одинаковые. Как это понимать. Если бы цвета значимых типов и ссылочных типов были разные, то тебе не пришлось бы объяснять, что AsyncVoidMethodBuilder это структура. Не подумай, что я придираюсь, я просто хочу сделать из твоих шикарных знаний в виде видеоуроков ещё и удобную интерпретацию для впитывания этих знаний.
в самом главном моменте обьяснения не обьяснил
Спасибо, было познавательно!
Спасибо за видео!
Спасибо за годный контент!)