Спроектируйте боевую систему action-RPG в стиле Diablo в Unreal Engine для онлайн-кооператива. У игроков много способностей с кулдаунами, стоимостью и скейлом по уровню; у врагов есть здоровье, сопротивления и взаимодействие с критами; и дизайнеры должны крутить каждое число — урон способностей, сопротивления, кривые скейла — без пересборки игры программистом. Урон должен проходить через единый конвейер митигации, чтобы криты, стихийные сопротивления и периодический урон складывались согласованно. Сессия мультиплеерная, поэтому здоровье, убийства и урон должны разрешаться авторитетно на сервере и быть неподделываемыми клиентом, при этом бой должен ощущаться отзывчивым (попадания и числа урона должны появляться без ожидания round-trip). Опишите, как структурированы способности, характеристики и конвейер урона, где живёт авторитет, и компромиссы вашего подхода.
Стройте всё на авторитете сервера: способности — как объекты на данных, компонент характеристик для здоровья, конвейер урона через FDamageEvent с митигацией. Сервер решает попадания и смерть, а клиенты лишь предсказывают косметику.
- ✗Доверять урону или здоровью, сообщённым клиентом, что открывает игру для тривиального читерства
- ✗Жёстко зашивать числа способностей в C++ вместо вынесения их в данные для дизайнеров
- ✗Применять урон в клиентских событиях overlap вместо разрешения попаданий на сервере
- →Как сделать числа урона отзывчивыми, несмотря на разрешение урона на сервере?
- →Как структурировать криты, стихийные сопротивления и периодический урон в конвейере?
Ключевые классы
UAbilityDataAsset— описание способности: стоимость, кулдаун, базовый урон, тип стихии, тег цели.UCombatComponent—UActorComponentна персонаже: активирует способности, ведёт кулдауны, инициирует трейсы попадания.UStatComponent— здоровье, мана, сопротивления, множители; единственный авторитетный источник характеристик.FDamageEvent/UDamageType— стандартная инфраструктура урона Unreal, расширенная стихией и флагом крита.
Модель данных
Способность — это данные, а не код: одна C++-машина исполнения читает UAbilityDataAsset. Урон описывается структурой FDamagePayload (источник, базовое значение, стихия, флаг крита), которая проходит конвейер митигации.
Поток данных
- Клиент жмёт навык → Server RPC
ActivateAbility(id). - Сервер проверяет кулдаун и стоимость по
UStatComponent, выполняет трейс/overlap. - По каждой цели формируется
FDamagePayload, проходит через сопротивления и криты вUStatComponent. - Сервер применяет итоговый урон, реплицирует здоровье и multicast'ом рассылает попадание для VFX и чисел урона.
Репликация
Здоровье и характеристики реплицируются только сервером. Способности активируются через Server RPC; косметика (анимации, VFX) предсказывается клиентом локально и подтверждается Multicast RPC. Числа урона показываются по multicast-событию, чтобы все видели согласованную картину.
Настройка дизайнером
Каждая способность — ассет UAbilityDataAsset. Кривые урона по уровню — UCurveTable. Сопротивления монстров — DataTable. Дизайнер балансирует бой без участия программиста.
Компромиссы
- Авторитет сервера vs. отзывчивость: сервер исключает читы, но добавляет задержку — компенсируется клиентским предсказанием косметики.
- Своя система vs. GAS: своя проще для маленькой команды, но GAS даёт готовую репликацию, эффекты и предсказание для масштаба.