𝐑𝐨𝐨𝐭𝐓𝐨𝐨𝐥 𝐁𝐥𝐨𝐠
Неожиданный дроп, месяц работы и встречайте - A Cold Love Story Remaster (V1.1) Да-да, хоть кто-то спустя 10 лет взялся за игру Лиама Викерса (Серьезно, он выпустил ее в 2015-м) Чем можем порадовать? - Подчистка от лишних файлов - залог оптимизации (Вес…
A Cold Love Story
Делюсь с вами роликом товарища по SSTWL про криппипасту/новеллу Лиама Викерса - A Cold Love Story
(Делюсь ночью, потому что так атмосфернее)
Ролик получился хорошим, длинным и интересным
А также он хорошо пересказал оригинальную крипипасту (которую я собственно не читал), поэтому узнал от нее некоторые новые моменты
Ссылочка: тык
(Ролик с трудом делался аж 3 месяца, поддержите его как никак)
Делюсь с вами роликом товарища по SSTWL про криппипасту/новеллу Лиама Викерса - A Cold Love Story
(Делюсь ночью, потому что так атмосфернее)
Ролик получился хорошим, длинным и интересным
А также он хорошо пересказал оригинальную крипипасту (которую я собственно не читал), поэтому узнал от нее некоторые новые моменты
Ссылочка: тык
(Ролик с трудом делался аж 3 месяца, поддержите его как никак)
YouTube
Визуальная Новелла от Создателя Дронов-Убийц
A Cold Love Story - одна из первых криппипаст Лиама Викерса, создателя Дронов-Убийц, которая в последствие стала основой для всех дальнейших его проектов. И в этом ролике мы пройдёмся настолько подробно по этой криппипасте, насколько это возможно. Приятного…
🔥3❤1
🎶Солнце мое, взгляни на меня🎶
🎶Моя ладонь превратилась в кулак🎶
Что ж.... Что ж.... Прошли недели, улетели месяцы, 1 год разработки и вот она - Портал Солвер Альфа
Безусловно, это не конец. Это далеко не конец
Но кого хотелось бы поблагодарить - вас. И каждого, кого я встретил в такое короткое время. Конечно, время не вернешь, моменты что были так и останутся в памяти
Но все равно, было весело проводить время вместе. Конечно кого-то перегнула внутренняя гордыня, кто-то не поделил любовный треугольник а кто-то еще просто не подрос лол
Даже если мы больше не увидимся - то помните, что было весело провести время с вами
А еще было приятно встретить вас на релизе Альфы! Я честно и не думал что вам так все понравится. Да, были баги, хотя фичи тоже были - кататься на лазерном релее это сильно)
Очень высоко оценили саундтреки, меню, оптимизацию (вау) и кастомизацию Солвера
Собственно еще раз благодарю команду, ее бывших участников и вообще всех тех, кого когда-либо встречал. Без вас бы этот день не случился!
🎶Моя ладонь превратилась в кулак🎶
Что ж.... Что ж.... Прошли недели, улетели месяцы, 1 год разработки и вот она - Портал Солвер Альфа
Безусловно, это не конец. Это далеко не конец
Но кого хотелось бы поблагодарить - вас. И каждого, кого я встретил в такое короткое время. Конечно, время не вернешь, моменты что были так и останутся в памяти
Но все равно, было весело проводить время вместе. Конечно кого-то перегнула внутренняя гордыня, кто-то не поделил любовный треугольник а кто-то еще просто не подрос лол
Даже если мы больше не увидимся - то помните, что было весело провести время с вами
А еще было приятно встретить вас на релизе Альфы! Я честно и не думал что вам так все понравится. Да, были баги, хотя фичи тоже были - кататься на лазерном релее это сильно)
Очень высоко оценили саундтреки, меню, оптимизацию (вау) и кастомизацию Солвера
Собственно еще раз благодарю команду, ее бывших участников и вообще всех тех, кого когда-либо встречал. Без вас бы этот день не случился!
❤🔥3❤1🔥1🎉1
Опыт штука прикольная, жаль только приходит со временем
Удивительно, но сегодня начнем с Portal De Solverio
Точнее - БЕКЕНД 💀
Иронично, что в Альфе есть оптимизация, но дьявол скрыт в деталях...
Примерно чтобы вы понимали спектр моей работы сейчас - мне нужно как хирург аккуратно работать с существующей кодовой базой Альфы, перестраивать ее, переписывать, дак еще выпускать патчи
А причина?
- Во-первых... код написан сомнительно, а за год разработки я не один раз наступал на грабли, так еще сроки - нужно было усердно все заматывать изолентой, чтобы это хотя бы запустилось хвхвхвхв)
- Та и во-вторых редактор карт, да! К нему мы стремимся! От чего нужно очень сильно изменить структуру текущего бекенда Альфы. Думаете только мне одному стремно?
Сейчас конечно я начал переписывать лазеры, хотя что значит переписывать... Логика не изменится, они как работали так и будут, но само взаимодействие очень сильно изменится, с опытом тут я могу выделить пару вещей:
-
UCLASS(MinimalAPI) - удобнейшая штучка для оптимизации. Говоря простым языком - в компиляцию пойдет не весь класс, а только то, что используется. То есть если будут какие-то функции, которые "просто оставлены", но никто с ними не работают - то они не пойдут в финальный билд. Уменьшает время компиляции!-
UInterface - Интерфейсы... Да В свое время я допустил большую ошибку, когда мне нужно было обновлять лазерные компоненты по-очереди (просто потому что так надо), я накатал небольшую подсистему ULaserSubsystem от UTickableWorldSubsystem (Подсистема, живущая в текущем мире и имеющая тик), и в ней я хранил ссылки на акторы лазерных элементов и там же обновлял их состояние в нужном порядке (TX -> RX -> Cube -> Relay).
Сами понимаете, хранить ссылки на каждый класс это... не круто как-то? Так еще у меня был САМЫЙ НЕЛЮБИМЫЙ КЛАСС в Портал Солвере - LaserClass.cpp, это была тупо затычка, которая всегда багалась и вылетала из-за ТУПЕЙШЕЙ рефлексии Анрила. То компонент удалялся, то неправильно регистрировал все, то вообще... да... Нет слов одни рыданья (Интересно как Альфа еще жива хвхвхв)
Поэтому сейчас начал жествую перепись кода и теперь все строится на абстрактных интерфейсах - на деле это жесть какая удобная штука!
Хотя возникает вопрос - как хранить интерфейсы в массиве? Сделать TArray<AActor*> и каждый тик делать каст на нужный интерфейс? Ха, размечтались...
-
TScriptInterface<T> - Контейнер интерфейсов. Обычно интерфейсы являются самостоятельными классами и трудно как-то "взять их", но тут Эпики на удивление постарались и сделали нам TScriptInterface - контейнер, что хранит ссылку на интерфейс, прикрепленный к определенному обьекту. И как бы сложите это и выше сказанное и у вас получится красивенький TArray<TScriptInterface<T>> - именно так и реализовано сейчас. А так как это массив, то его можно спокойно перебрать и делать то, что хотите (вот на примере моего интерфейса ILaserInterface):for (const TScriptInterface<ILaserInterface>& Laser : LaserArray) // Перебираем каждый элемент массива
if (Laser && IsValid(Laser.GetObject())) // Если сам интерфейс и его родитель существуют (проверяйте, ибо частенько спасает от вылетов в финальной сборке)
Laser->TickLaser(DeltaTime); // То выполняем функцию через интерфейс (В моем случае тик лазера)
(Скоро будет второй пост, ибо есть что рассказать)
❤🔥3❤1🎉1🤩1🫡1
Успешно отсортировано и закомпилино 74 файлов
Теперь проект отсортирован не только в Контент Браузере, а еще в папке Source (с кодом)
(Не обращайте внимание на 4 файла, классы компилились "пачками", всего их 74)
Теперь проект отсортирован не только в Контент Браузере, а еще в папке Source (с кодом)
(Не обращайте внимание на 4 файла, классы компилились "пачками", всего их 74)
Могу выделить основные разделы:
- Elements - Классы всех элементов головоломок
- Interfaces - Интерфейсы
- Settings - 2 класса для настроек игры (да, в нашей архитектуре GConfig не раскинут по всему бекенду, а красиво собран в 1 классе)
- Subsystems - Разного рода подсистемы (Discord, GameJolt, Лазеры и тд.)
- UI - Все классы для UI менюшек
- UMG - Классы кастомных UI элементов (А вы думали мы вручную в блюпринтах для каждой кнопочки делаем подсветку текста? Ага)
Так что... проблемы компиляции - это проблемы Анрила❤2🔥1💘1
Второй пост!
Тут я решил оставить вам самую вишенку на торте:
-
Почему? Когда вы создаете блюпринт, то Анрил вокруг вашего С++ класса создает свою обертку, хотя даже нет... виртуальную среду вокруг С++ класса. Благодаря ей вы можете редактировать этот блюпринт и тд. Но будем честны - если в уровне будет 200+ блюпринтов, то игра банально будет лагучей (И это правда, по ошибке молодости скажу - в Портал Солвер Демо десятки блюпринтов, даже статичных обьектов, вызывало большущие лаги). Но есть небольшая хитрость - то, что вы "делаете мышкой" можно сделать кодом!
Имеется ввиду, что загрузить и установить статик меш (к примеру-) можно прямо в коде, а основные параметры вывести в UPROPERTY и тогда можно отказаться от создания отдельного блюпринта. Но возникает логичный вопрос - как?
-
Чтобы быстро скопировать нужный путь: ПКМ по ассету -> Copy Object Path. И да - НЕ используйте его в любой другой функции, кроме конструктора класса!
А как сделать чтобы обьект мог иметь 2 статик меша по выбору? Тут тоже есть решение
-
И теперь вспоминая тот гайд про OnConstruction можем применить эти знания для переключения между статик мешами! (И вот вам домашнее задание хвхвхвх)
Да.... 8 тысяч символов в 2 поста... теперь я буду здесь рассказывать про прогресс и опыт, ибо вы меня очень сильно порадовали на релизе Альфы и поэтому я уже не могу просто опустить руки и пойти отдыхать :)
Тут я решил оставить вам самую вишенку на торте:
-
Blueprints -> C++ - Из блюпринтов в С++? Именно: это и есть одна из задач переписи бекенда - избавиться от блюпринтов и перейти на чистый спавн С++ классов в мире (Если кто не в курсе - в меню "Spawn Actor" можно заспавнить как блюпринт, так и чисто С++ класс)Почему? Когда вы создаете блюпринт, то Анрил вокруг вашего С++ класса создает свою обертку, хотя даже нет... виртуальную среду вокруг С++ класса. Благодаря ей вы можете редактировать этот блюпринт и тд. Но будем честны - если в уровне будет 200+ блюпринтов, то игра банально будет лагучей (И это правда, по ошибке молодости скажу - в Портал Солвер Демо десятки блюпринтов, даже статичных обьектов, вызывало большущие лаги). Но есть небольшая хитрость - то, что вы "делаете мышкой" можно сделать кодом!
Имеется ввиду, что загрузить и установить статик меш (к примеру-) можно прямо в коде, а основные параметры вывести в UPROPERTY и тогда можно отказаться от создания отдельного блюпринта. Но возникает логичный вопрос - как?
-
ConstructorHelpers::FObjectFinder<T> - Функция, что загружает ассет по определенному пути в конструкторе класса (Можно сказать на моменте его спавна в мире). Прикольная штука, но у меня она перестала работать с половинной ассетов ¯\_(ツ)_/¯ (Sound Cue и Ниагары-Системы)Чтобы быстро скопировать нужный путь: ПКМ по ассету -> Copy Object Path. И да - НЕ используйте его в любой другой функции, кроме конструктора класса!
А как сделать чтобы обьект мог иметь 2 статик меша по выбору? Тут тоже есть решение
-
StaticLoadObject - то же самое, что ConstructorHelpers::FObjectFinder<T>, но является низкоуровневым (и гибким) собратом, не ломает проект если его вызывать не в конструкторе класса, работает со всеми ассетами (как минимум трудностей я не встретил) и вообще он плюс вайб активити (Использование показано на фотке 1)И теперь вспоминая тот гайд про OnConstruction можем применить эти знания для переключения между статик мешами! (И вот вам домашнее задание хвхвхвх)
Да.... 8 тысяч символов в 2 поста... теперь я буду здесь рассказывать про прогресс и опыт, ибо вы меня очень сильно порадовали на релизе Альфы и поэтому я уже не могу просто опустить руки и пойти отдыхать :)
❤3🔥1🤔1
Наконец-то сделал то, что давно хотел сделать - использовать интерфейсы
Да, я знаю, использовать
Этим то и отличаются начинающие программисты от опытных. Опытные пишут немного сложно, но масштабируемо. И когда действительно надо расширить функционал - оно легко расширяется.
На 2-й фотке создаем новый интерфейс
На 3-й это результат того, как сильно упростился код. А куда подевалась вся логика? Она ушла на 4-ю фотку. Теперь каждый класс сам решает при каких условиях ему можно подсвечиваться
(От чего мне больше не надо лесть в Солвер Ган, чтобы что-то там добавить)
Да, я знаю, использовать
IsA(T::StaticClass())) это довольно таки плоховато... Хотя знаете, когда только пишешь код, думаешь "Ай ладно, 1 раз сделаю и ничего"Этим то и отличаются начинающие программисты от опытных. Опытные пишут немного сложно, но масштабируемо. И когда действительно надо расширить функционал - оно легко расширяется.
Про себя я могу сказать... Если только в UI - спустя +-7 месяцев на С++ я научился создавать реально масштабируемые структуры, от чего добавление нового UI не вызывает головной боли
На 2-й фотке создаем новый интерфейс
IHighlightableObjectInterfaceНа 3-й это результат того, как сильно упростился код. А куда подевалась вся логика? Она ушла на 4-ю фотку. Теперь каждый класс сам решает при каких условиях ему можно подсвечиваться
(От чего мне больше не надо лесть в Солвер Ган, чтобы что-то там добавить)
🔥2❤🔥1
Лаааадно, такого у меня еще не было со времен переписи UI...
Что могу сказать:
- Теперь все кубы являются самостоятельными акторами и не унаследуются от базового класса кубиков
- Добавлены новые интерфейсы:
- Также охрененно проделана работа в области раздатчика кубов - теперь раздатчик спавнит не блюпринт куба, а сам куб (вот о чем я вам говорил ранее)
- Ну а также под конец завез нам
Зачем? У меня как-то была идея сделать 2 куба в 1: Лазерный + Обычный и переключатель между типами. Но у них сильно отличается логика и их смешивание может полностью убить масштабируемость кода, читабельность и в первую очередь оптимизацию - зачем вам в обычном кубике логика для лазерного? Во-во..
А так я жесть устал, всем спокойной ночи! (Или доброе утро)
Что могу сказать:
- Теперь все кубы являются самостоятельными акторами и не унаследуются от базового класса кубиков
- Добавлены новые интерфейсы:
IIndicatorCubeInterface и IGrabbableInterface- Также охрененно проделана работа в области раздатчика кубов - теперь раздатчик спавнит не блюпринт куба, а сам куб (вот о чем я вам говорил ранее)
- Ну а также под конец завез нам
ABaseCubeElement, который хранит лишь параметр какого типа кубов он относится (обычный, лазерный и тд.). И перед стартом игры он заменяется на соответствующий куб с полной логикой (Сделано для редактора карт)Зачем? У меня как-то была идея сделать 2 куба в 1: Лазерный + Обычный и переключатель между типами. Но у них сильно отличается логика и их смешивание может полностью убить масштабируемость кода, читабельность и в первую очередь оптимизацию - зачем вам в обычном кубике логика для лазерного? Во-во..
А так я жесть устал, всем спокойной ночи! (Или доброе утро)
❤2🔥1🤩1