Всем привет!
🔥 Новое видео на канале 🔥
Краткий план лекции следующий:
🎯 Изучаем Doxygen
🎯 Создаем работу в Jenkins для генерации доков
🎯 Рассматриваем GitHub Workflows
🎯 Собираем неоптимизированный билд
https://youtu.be/wvy6lLt1YfY
🔶 Итоговая документация
🔶 Все ссылки из видео
Ресурсы:
🔴 LifeEXE School
🔴 Группа ВКонтакте
🔴 Twitter
🔴 GitHub
Поддержать канал:
🔴 Patreon
🔴 PayPal Donate
#unrealengine #ue5 #gamedev #devops #doxygen #github #test_coverage #code_coverage #unrealengine5 #ue4 #lifeexe #lifeexecode #cplusplus
🔥 Новое видео на канале 🔥
Краткий план лекции следующий:
🎯 Изучаем Doxygen
🎯 Создаем работу в Jenkins для генерации доков
🎯 Рассматриваем GitHub Workflows
🎯 Собираем неоптимизированный билд
https://youtu.be/wvy6lLt1YfY
🔶 Итоговая документация
🔶 Все ссылки из видео
Ресурсы:
🔴 LifeEXE School
🔴 Группа ВКонтакте
🔴 GitHub
Поддержать канал:
🔴 Patreon
🔴 PayPal Donate
#unrealengine #ue5 #gamedev #devops #doxygen #github #test_coverage #code_coverage #unrealengine5 #ue4 #lifeexe #lifeexecode #cplusplus
YouTube
33. Документация проектов Unreal Engine. Doxygen. GitHub Workflows. Jenkins. Автоматизация UE
#unrealengine #gamedev #devops #CI #ue5 #unrealengine5 #ue4 #lifeexe #lifeexecode #doxygen #githubworkflows #jenkins #python #conan
Мой курс «Unreal Engine — полное руководство по разработке на С++»
https://www.udemy.com/course/unrealengine/?referral…
Мой курс «Unreal Engine — полное руководство по разработке на С++»
https://www.udemy.com/course/unrealengine/?referral…
🔥35👍8❤1
Минутка кода под утренний кофеёк
В
UE5
появился удобный макрос для логирования — UE_LOGFMT
.Он позволяет логировать строки более гибко и безопасно.
Пример использования:
#include "Logging/StructuredLog.h"
DEFINE_LOG_CATEGORY_STATIC(LogSlasherGame, All, All);
const FString Name = "Patrick Bateman";
const bool IsDead = false;
const int32 Ammo = 10;
UE_LOGFMT(LogSlasherGame, Display,
"Name: {0}, is alive: {1}, ammo: {2}", Name, !IsDead, Ammo);
Сравнение с классическим
UE_LOG
:#include "Logging/StructuredLog.h"
DEFINE_LOG_CATEGORY_STATIC(LogSlasherGame, All, All);
const FString Name = "Patrick Bateman";
const bool IsDead = false;
const int32 Ammo = 10;
UE_LOGFMT(LogSlasherGame, Display,
"Name: {0}, is alive: {1}, ammo: {2}", Name, !IsDead, Ammo);
UE_LOG(LogSlasherGame, Display,
TEXT("Name: %s, is alive: %s, ammo: %d"),
*Name, IsDead ? TEXT("false") : TEXT("true"), Ammo);
UE_LOGFMT
поддерживает именованные аргументы:#include "Logging/StructuredLog.h"
DEFINE_LOG_CATEGORY_STATIC(LogSlasherGame, All, All);
const FString Name = "Patrick Bateman";
const bool IsDead = false;
const int32 Ammo = 10;
UE_LOGFMT(LogSlasherGame, Display,
"Name: {name}, is alive: {alive}, ammo: {ammo}", Name, !IsDead, Ammo);
Результат логирования везде одинаковый:
Name: Patrick Bateman, is alive: true, ammo: 10
UE_LOGFMT
использует современный подход к форматированию строк — string interpolation, подобно std::format (С++20), или анриловскому FString::Format
, что обеспечивает безопасность типов (type safety) и улучшает читаемость.Не забудьте, что для использования
UE_LOGFMT
необходимо подключить заголовочный файл:#include "Logging/StructuredLog.h"
Patreon | Boosty | PayPal
GitHub | LifeEXE School | Itch | X | Wiki | Курс по UE
#unrealengine #gamedev #lifeexe #code #cpp #code_hints #lifeexeEDU
Please open Telegram to view this post
VIEW IN TELEGRAM
50🔥111 32👍15❤8🐳1🏆1
Небольшой пост о UML-диаграммах и диаграммах в целом
Сам не фанат детализированных диаграмм, но иногда полезно их применять для наглядного объяснения базовых концептов и функциональности.
Популярные сервисы вроде
drawio, lucidchart, miro или axivion suite
, конечно, справляются с этой задачей. Однако они перегружены, и нужно приложить усилия, чтобы всё выглядело аккуратно и читабельно. Плюс некоторые фичи доступны только по подписке. Короче, удобнее на листе бумаги все накидать 😁Но имеется один отличный минималистичный и полностью бесплатный инструмент, который может помочь с диаграммами:
Сервис использует собственный декларативный язык, который автоматически выравнивает все элементы. Пример простой диаграммы классов (рендер в приложенном изображении):
classDiagram
class Character {
-string name
}
class Supervillain {
+doBadThings()
}
class WeaponComponent {
-int damage
+attack()
}
class HealthComponent {
-int health
+heal()
}
Character <|-- Supervillain : is-a
Supervillain *-- WeaponComponent : has
Supervillain *-- HealthComponent : has
Mermaid
поддерживает разные типы диаграмм (не только UML
):• классов
• состояний
• последовательностей
• Ганта
• чарты
и другие.
У
Mermaid
имеется удобный live-редактор, в котором можно экспериментировать: https://mermaid.liveДоки отличные, все осваивается за пару часов, если знакомы с
UML
: https://mermaid.js.org/introПоддерживаются стили, так что внутренний художник будет удовлетворен
Инструмент легко интегрируется с платформами, такими как
Notion, Jira, GitBook
и многими другими, поскольку все рендирится на JavaScript
. Загуглите, есть даже плагин для VSCode.
Плюс это ещё и
open-source проект
(зацените кстати их модный markdown, с интеграцией диаграмм):https://github.com/mermaid-js/mermaid
Не хватает только кастомных координат. Хотелось бы иметь возможность двигать блоки самостоятельно. Возможно добавят со временем данную фичу. Тогда будет идеально.
В качестве бонуса есть ещё один мини сервис:
https://nomnoml.com
В вики все ссылки добавил
#lifeexe #tools #uml #code #gamedev #mermaid
Please open Telegram to view this post
VIEW IN TELEGRAM
❤36👍21🔥17 5👾3
Непостоянная рубрика: Субботний C++
Сегодня в меню очевидный, но не всегда применяемый подход:
Immediately Invoked Lambda Expression (IILE)
Почему const — это важно?
Неизменяемость (immutability) — залог надежного и понятного кода. Использование const там, где это возможно, помогает компилятору отлавливать ошибки и показывает намерения программиста яснее. Когда другой человек читает ваш код и видит const, снижается когнитивная нагрузка на мозг — «запоминать изменения данного значения не надо — расслабься». Const correctness является важной практикой в C++.
Проблематика
В простых случаях инициализация констант не вызывает проблем:
const int c_maxPlayers = 100;
const double c_scale = getScaleFactor() * 1.5;
const bool c_enabled = check() || FORCE_ENABLE;
const int c_healthModifier = bHealing ? 20 : 0;
Но что делать, если для вычисления значения константы требуется несколько шагов, временные переменные, циклы или условия?
float c_calculatedDamage = getBaseDamageValue();
if (targetAimed(calculatedDamage)) {
for (int i = 0; i < c_effectCount; ++i) {
calculatedDamage += getBonusDamage(i);
}
}
Традиционные подходы — вынести логику в отдельную именованную функцию или отказаться от const — не всегда идеальны. Создание отдельной функции может быть избыточным, если логика используется только один раз. Отказ от const снижает безопасность и выразительность кода.
Immediately Invoked Lambda Expression (IILE)
Здесь на помощь приходит использование немедленно вызываемого лямбда-выражения (IILE). Мы определяем лямбда-функцию, которая инкапсулирует всю сложную логику инициализации, и тут же вызываем её. Результат этого вызова и присваивается нашей константе.
Как это выглядит:
const auto myLambda = [](){ return 13; }();
Скобочки форева
const auto c_calculatedDamage = [&]() {
float tempDamage = getBaseDamageValue();
if (targetAimed(tempDamage)) {
for (int i = 0; i < c_effectCount; ++i) {
tempDamage += getBonusDamage(i);
}
}
return tempDamage;
}();
Преимущества IILE для инициализации
const
(или даже constexpr
, если лямбда соответствует требованиям), даже если её вычисление многоэтапное.Альтернативный синтаксис (C++17)
В C++17 можно использовать
std::invoke
, хотя для IILE прямой вызов () обычно предпочтительнее и понятнее:#include <functional>
// ...
const auto c_anotherConstant = std::invoke([] {
// ...
return 13;
});
Ссылки
Patreon | Boosty | PayPal
GitHub | LifeEXE School | Itch | X | Wiki | Курс по UE
#cpp #tipsandtricks #code #fun #lifeexe #lifeexecode #lifeexeEDU
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥83❤16👍9❤🔥2
Media is too big
VIEW IN TELEGRAM
На
FAB
завезли топовый контент — RDR
System
Проект, написанный на C++, демонстрирует интеграцию Advanced Locomotion System Refactored с возможностями Motion Matching из проекта Game Animation Sample
#unrealengine #ue5 #fab #gamedev #gasp #als #sample #code #assets #lifeexe #lifeexecode
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥44 14❤4👍3 1 1
В новом апдейте Visual Studio 2022 17.14 огненные фичи
Добавлена возможность отлаживать Blueprint'ы непосредственно в Visual Studio. Это позволяет просматривать стек вызовов блюпринт-функций и их локальные переменные прямо в IDE —
[Изображение1]
Соответствующие окна в меню Visual Studio:
Debug > Windows > Call Stack
Debug > Windows > Locals
Отлаживать так намного удобнее + время переключения между Visual Studio и Unreal Editor сократится. Это прямо кайф!
Динамическая отладка C++ — это новая фича компилятора и IDE, которая позволяет сохранить производительность оптимизированных сборок, предоставляя при этом удобство отладки, характерное для неоптимизированных сборок.
Проблематика:
Думаю, каждый сталкивался с переменными, значения которых невозможно посмотреть под отладчиком, потому что они были оптимизированы компилятором —
[Изображение2]
Как решать данную проблему?
#pragma optimize( "", off )
/* unoptimized code section */
int please_let_me_live_var {13};
#pragma optimize( "", on )
В Unreal Engine имеется свой парный макрос для этого:
UE_DISABLE_OPTIMIZATION
int please_let_me_live_var {13};
UE_ENABLE_OPTIMIZATION
Собственный макрос в UE обусловлен тем, что синтаксис pragma варьируется между компиляторами.
1. Ставим конфигурацию проекта в Release.
2. Включаем фичу в пропертях проекта
[Изображении3]:
Advanced > Use C++ Dynamic Debugging > Yes
3. Результат можно видеть на [Изображении4]
C++23
, некоторые автокомплиты для CMAKE
и улучшения для GitHub
Copilot
— куда ж без него На моём канале есть видео по теме:
#visualstudio #vs #code #unrealengine #ue5 #gamedev #lifeexe #lifeexecode
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥45❤7😱6 4👍2 1
Зацените чувство юмора авторов книги по C++ 1997 года от Bell Labs
Слово
ruminate
в английском языке имеет два значения:— жевать жвачку, буквально, как делают коровы
— размышлять глубоко и вдумчиво
Фамилия Барбары — Му
Обложка рекурсивная: женщина на обложке (походу Барбара) читает книгу, на которой изображена она сама.
#code #book #cpp #gamedev #lifeexe #lifeexecode #humor
Please open Telegram to view this post
VIEW IN TELEGRAM
😁38👍8❤🔥5⚡2❤1🤯1👌1👾1 1
В эфире рубрика выходного дня: Воскресный C++
Numeric limits в стандарте C++ и в Unreal Engine
На Boosty и Patreon расширенная статья с множеством интерактивных примеров в Compiler Explorer
std::numeric_limits
в C++ — это стандартный шаблонный класс, который предоставляет информацию о свойствах числовых типов, например:infinity,
quiet_NaN,
signaling_NaN
и другие.Полная спецификация на cppreference.com
Простейший пример использования:
#include <limits>
#include <print> // C++23
int main()
{
std::println("Max int: {}", std::numeric_limits<int>::max());
std::println("Min double: {}", std::numeric_limits<double>::min());
std::println("Lowest float: {}", std::numeric_limits<float>::lowest());
std::println("Double epsilon: {}", std::numeric_limits<double>::epsilon());
return EXIT_SUCCESS;
}
Ключевые особенности
Безопасность
Вместо «магических чисел» (например,
2147483647
для int
), вы используете std::numeric_limits<int>::max()
. В итоге код становится более читаемым и переносимым (платформонезависимым).Портируемость
int,
float,
double, uint64_t
, а также с пользовательскими числовыми типами, если для них существует специализация шаблона numeric_limits
.Чистота кода
Когда реально нужен
NaN
.В Unreal Engine имеется собственный шаблон
TNumericLimits<T>
— это аналог std::numeric_limits
, реализованный в движке. Заголовочный файл находится по адресу:
Runtime/Core/Public/Limits.h
Применение абсолютно аналогичное, как и в стандартном C++:
#include "Math/NumericLimits.h"
#include "Logging/StructuredLog.h"
DEFINE_LOG_CATEGORY_STATIC(LogNumLimitsTest, All, All);
void NumLimitsTest()
{
const int32 MaxInt = TNumericLimits<int32>::Max();
const int32 MinInt = TNumericLimits<int32>::Min();
const float MaxFloat = TNumericLimits<float>::Max();
const float MinFloat = TNumericLimits<float>::Min();
UE_LOGFMT(LogNumLimitsTest, Display, "Int32: Min={0}, Max={1}", MinInt, MaxInt);
UE_LOGFMT(LogNumLimitsTest, Display, "Float: Min={0}, Max={1}", MinFloat, MaxFloat);
}
std::numeric_limits
— читаем раздел Use of standard libraries. Поэтому можно выбирать любой подходящий под вашу конкретную ситуацию шаблон.Всем чистого кода
Patreon | Boosty | PayPal
GitHub | X | LifeEXE School | Itch | Wiki | Курс по UE
#code #cpp #code_hints #lifeexeEDU #unrealengine #ue5 #gamedev #lifeexe #lifeexecode #best_practice #numeric_limits #clean_code
Please open Telegram to view this post
VIEW IN TELEGRAM
6🔥24 16❤9 2🦄1
В эфире рубрика выходного дня: Воскресный C++
Написал большую статью на тему:
«Asserts в стандарте C++ и в Unreal Engine»
❗️ На Boosty и Patreon полная версия с множеством примеров!
По традиции сначала разбираем как все работает на чистом
C++, а потом смотрим, что происходит в Unreal Engine.
Assertions — это утверждения, проверяющие предположения программиста о корректности кода. Они помогают выявлять ошибки и документировать инварианты.
Инвариант — это условие, которое должно быть истинным всегда в определённом контексте.
Зачем нужны assertions?
Виды assertions
В стандартном C++ основной инструмент для реализации утверждений — это макрос препроцессора
assert
, определенный в заголовочном файле <cassert>
:stderr
и немедленно завершает программу путем вызова функции std::abort()
double div(double numerator, double denominator)
{
assert(denominator != 0.0);
return numerator / denominator;
}
Стандартный макрос
assert
не имеет встроенного параметра для пользовательских сообщений. Однако существуют две распространенные идиомы для добавления диагностики, которая будет выведена в диагностическом сообщении в случае сбоя assert(divisor != 0 && "Divisor cannot be 0");
assert(("Divisor cannot be 0", divisor != 0));
Распространенная ошибка при использовании
assert
— это включение в проверяемое выражение кода с побочными эффектами. Проблема в том, что когда определен макрос
NDEBUG
, все выражение внутри assert
удаляется из кода. Это может привести к тому, что логика программы в отладочной и релизной сборках будет отличаться. assert(InitializeSubsystem());
[[maybe_unused]] const bool bSuccess = InitializeSubsystem();
assert(bSuccess);
Unreal Engine расширяет стандартный макрос
assert
, добавляя дополнительные возможности к рантайм проверкам, Имеются следующие семейства: check
, verify
, ensure
.Семейство
check
является прямым эквивалентом стандартного assert
в Unreal Engine. Сбой check
указывает на критическую ошибку в программе, и выполнение немедленно останавливается void AMyActor::CalculateJumpVelocity(AActor* JumpTarget, FVector& JumpVelocity)
{
check(JumpTarget != nullptr);
}
Остальные макросы данного семейства:
check, checkf, checkSlow, checkfSlow, checkCode, checkNoEntry, checkNoReentry, checkNoRecursion, unimplemented
Следующее семейство макросов является решением проблемы побочных эффектов. Выражение внутри макроса
verify
выполняется всегда, независимо от конфигурации сборки.Полный список макросов:
verify, verifyf, verifySlow
Данное семейство макросов используется для сообщения о нефатальных ошибках. Программа не завершает работу, а отправляет отчет со стеком вызовов в Crash Reporter и продолжает выполнение:
ensure, ensureAlways, ensureMsgf, ensureAlwaysMsgf
static_assert
check
verify
checkSlow
ensure
checkNoEntry
или unimplemented
checkNoRecursion
checkNoReentry
В статье на Boosty и Patreon подробнее про каждый из макросов и static_assert
Всем чистого кода
Patreon | Boosty | PayPal
GitHub | X | LifeEXE School | Itch | Wiki | Курс по UE
#code #cpp #code_hints #lifeexeEDU #unrealengine #ue5 #gamedev #lifeexe #lifeexecode #best_practice #assert #clean_code
Please open Telegram to view this post
VIEW IN TELEGRAM
21🔥38 10👍9❤5🦄1 1
Поздравляю с началом нового учебного года!
Забирайте бесплатный купон на 100 мест на мой курс «Unreal Engine — полное руководство по разработке на С++»
Статистика по курсу на сегодня следующая
Студенты из
Всем спасибо за отзывы и прохождение!
Patreon | Boosty | PayPal
GitHub | X | LifeEXE School | Itch | Wiki | Курс по UE
#code #cpp #lifeexeEDU #unrealengine #ue5 #gamedev #lifeexe #lifeexecode #udemy #course #shooter #free #coupon
Please open Telegram to view this post
VIEW IN TELEGRAM
Udemy
Unreal Engine — полное руководство по разработке на С++
Раскройте возможности C++ для разработки игр в Unreal Engine
🔥76❤21 6❤🔥3⚡2🦄1 1
This media is not supported in your browser
VIEW IN TELEGRAM
Вышла
Visual Studio 2026 Insiders
— так теперь называется preview сборка. Скачать бесплатную Community версию можно по ссылке Внутри:
Подробнее можно почитать в блоге
и также в тему
#vs #code #cpp #gamedev #lifeexe #lifeexecode
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥23❤9👍6🦄1 1
С днём программиста всех причастных!
И да.. стандарт
#day256 #code #cpp #programmer_day #gamedev #lifeexe #lifeexecode #humor
Please open Telegram to view this post
VIEW IN TELEGRAM
❤30😁26🔥9🎉8🤯4👍3 3🦄2
Media is too big
VIEW IN TELEGRAM
В новый Unreal Engine 5.7 завезли ИИ ассистента — плагин AIAssistant, который находится по адресу:
Engine\Plugins\Experimental\AIAssistant
Плагин элементарный: он просто открывает веб-морду Epic Developer Assistant в отдельном окне редактора движка, и, кстати, работает без логина:
Всё выглядит так, что разработчики, создавая плагин для интеллекта искусственного решили пренебречь интеллектом естественным.
Лапидарно — несколько моментов, которые прямо бросаются в глаза
TSet
в простейшем случае для 14 символов? Возможно, конечно автор изучал структуры данных на данном коде — кто знает:FString FAIAssistantConfig::GetMainUrlAsRegexString() const
{
static const TSet<FString::ElementType> CharactersToEscape{
'.', '*', '+', '?', '(', ')', '[', ']', '{', '}', '^', '$', '|', '\\',
};
FString Escaped;
Escaped.Reserve((MainUrl.Len() * 2) + 2 /* Allow for regex anchors */);
Escaped += FString::ElementType('^');
for (const FString::ElementType Character : MainUrl)
{
if (CharactersToEscape.Contains(Character))
{
Escaped += FString::ElementType('\\');
}
Escaped += Character;
}
Escaped += FString::ElementType('$');
Escaped.Shrink();
return Escaped;
}
TSet
тут избыточен — создаётся хеш-таблица с бакетами и метаданными для всего нескольких статических символов. Хватит switch/if
или простейшей строки-набора:static const FString CharsToEsc = TEXT(".+*?()[]{}^$|\\");
FString::ElementType
в данном случае только усложняет читаемость — можно смело использовать TCHAR.
FString
имеет методы Append
и AppendChar
, которые аккуратно избавят от громоздких конструкций вида += FString::ElementType
Escaped += FString::ElementType('^');
Escaped.AppendChar('^');
GetMainUrlAsRegexString
привязана к классу. Очевидно, её можно освободить или оформить как часть библиотеки утилит, передавая MainUrl
параметром. Это разблокирует (помимо славы выдающегося архитектора ПО):IMPLEMENT_SIMPLE_AUTOMATION_TEST
, хотя Automation Spec
уже давно доступен. Ничего критичного, но зачем тянуть старое в новом плагине.Patreon | Boosty | PayPal
GitHub | X | LifeEXE School | Itch | Wiki | Курс по UE
#code #cpp #plugin #unrealengine #ue5 #gamedev #lifeexe #lifeexecode #ai #ai_assistant #tests #code_review
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥34 10🦄6 4❤2😁2⚡1👍1