9

Делаю игру на Unity3d. Эпизод 4: Атака

Здравствуйте, дорогие Пикабушники и Пикабушницы!

Сегодня расскажу Вам, как в моей игре устроена система атаки!

Поведение атаки, так же как и любое другое, реализуется с помощью компонентов.

В компоненте ComboAttackDataComponent настраиваются все цепочки атак юнитов:

Делаю игру на Unity3d. Эпизод 4: Атака Gamedev, Разработка, Unity, Инди, Программирование, Инди игра, Компьютерные игры, IT, IT юмор, Мемы, Юмор, Unity3D, Паттерны, Видео, Без звука, Короткие видео, YouTube, Длиннопост

тонкая настройка атаки

В поле impact agents указываются агенты воздействия, которые будут как-то влиять на цели. У каждого такого агента есть своя настройка списка применяемых воздействий:

Делаю игру на Unity3d. Эпизод 4: Атака Gamedev, Разработка, Unity, Инди, Программирование, Инди игра, Компьютерные игры, IT, IT юмор, Мемы, Юмор, Unity3D, Паттерны, Видео, Без звука, Короткие видео, YouTube, Длиннопост

Этот агент нанесет урон, толкнет и оглушит противника!

Так же атака может модифицировать параметры юнита:

Делаю игру на Unity3d. Эпизод 4: Атака Gamedev, Разработка, Unity, Инди, Программирование, Инди игра, Компьютерные игры, IT, IT юмор, Мемы, Юмор, Unity3D, Паттерны, Видео, Без звука, Короткие видео, YouTube, Длиннопост

Во время атаки скорость передвижения юнита будет снижена.

А вот как это сейчас выглядит:

Все подробности вместе с кодом можете увидеть в полном видео. Приятного просмотра!

С любыми вопросами приглашаю в комментарии!

Правила сообщества

ОБЩИЕ ПРАВИЛА:

- Уважайте чужой труд и используйте конструктивную критику

- Не занимайтесь саморекламой, пишите качественные и интересные посты

- Никакой политики


СТОИТ ПУБЛИКОВАТЬ:

- Посты о Вашей игре с историей её разработки и описанием полученного опыта

- Обучающие материалы, туториалы

- Интервью с опытными разработчиками

- Анонсы бесплатных мероприятий для разработчиков и истории их посещения;
- Ваши работы, если Вы художник/композитор и хотите поделиться ими на безвозмездной основе

НЕ СТОИТ ПУБЛИКОВАТЬ:

- Посты, содержащие только вопрос или просьбу помочь
- Посты, содержащие только идею игры

- Посты, единственная цель которых - набор команды для разработки игры

- Посты, не относящиеся к тематике сообщества

Подобные посты по решению администрации могут быть перемещены из сообщества в общую ленту.

ЗАПРЕЩЕНО:

- Публиковать бессодержательные посты с рекламой Вашего проекта (см. следующий пункт), а также все прочие посты, содержащие рекламу/рекламные интеграции

- Выдавать чужой труд за свой

Подобные посты будут перемещены из сообщества в общую ленту, а их авторы по решению администрации могут быть внесены в игнор-лист сообщества.


О РАЗМЕЩЕНИИ ССЫЛОК:

Ссылка на сторонний ресурс, связанный с игрой, допускается только при следующих условиях:

- Пост должен быть содержательным и интересным для пользователей, нести пользу для сообщества

- Ссылка должна размещаться непосредственно в начале или конце поста и только один раз

- Cсылка размещается в формате: "Страница игры в Steam: URL"

1
Автор поста оценил этот комментарий

Технически это не ecs

Судя по скринам и видео - это классический ECS с кучей mono-компонентов на каждом gameObject'е.

А почему выбирают ddd в играх? Да потому что система ориентированная на данные очень гибкая и хорошо подходит для разработки игр. Программисты описывают логику игрового мира в системах или других логических единицах, а гейм дизайнеры играются с конфигами и могут делать разные интересные штуки просто комбинируя компоненты.

Да не подходит ddd и ECS для игр. Просто потому что это всё сжирает процессорное время. Когда в играх во главу угла ставят данные, то они начинают нещадно лагать.

Это всё удобно для прототипирования или когда ты пилишь конвейерные проекты и твоя работа фактически сводится в разработке инструментария для GD/LD, где они с этими компонентами и данными могут играться бесконечно, собирая объекты из конструктора. Но это конструктор стоит денег.

Вот банально у вас в видосе 6 mono-компонентов, которые только попали в кадр. И Unity будет обрабатывать каждый из них отдельно. Каждому вызовет Update, FixedUpdate и т.п., когда это всё можно объединить в один, который через ООП будет наследовать интерфейсы и прочее. GD не сможет настолько гибко играться, но у него будет набор Characters*, из которых он сможет собрать префабы персонажей. И это всё будет работать значительно быстрее.

Ладно, player, чаще всего один. Но те же enemy спавнятся пулами, там эти проблемы начинают тупо множиться с каждым новым enemy.

Иллюстрация к комментарию
раскрыть ветку (1)
2
Автор поста оценил этот комментарий
В ролике про игровой мир я показывал, что я управляю циклом апдейтов. Я не регистрирую апдейты в своих компонентах, поэтому юнити обходит их стороной. Вместо этого у меня свой контроллер обновления, который вызывает их только там, где надо. И большинство компонентов - это data, компоненты, в которых вообще нет логики. Поэтому хоть 6 компонентов, хоть 600.
Я нагружал сцену и с 500 врагов забитых компонентами, с деревьями поведения и прочим, мой сетап спокойно выдаёт 100 фпс.
понятно, что 500 юнитов не будет в кадре, они будут размазаны по локациям. И когда я добавлю logic lod, система будет ещё производительней за счёт отсечения лишней логики у дальних объектов.
Ну а так да, конечно, вся эта система требует ресурсов для своей внутренней логики. Но с учётом спицифики моей игры, моих идей и планов, я могу позволить себе это. И запас производительности имеется.
А по поводу наследования я осмелюсь возразить. Потому что наследование ломается, когда в игре появляется глубина. Когда куча юнитов с абсолютно разным поведением. Одни умеют ходить, другие - нет. Одни умеют бить, другие - нет. Одни бьют, другие стреляют, третьи заклинания кастуют, а четвертые могут только лечить, а пятые только строить. А супер юнит умеет делать это все сразу. А составные враги, когда платформа движется, а несколько пушек на ней по своей логике поражают разные типа целей. Выбрав наследование сразу стреляешь себе в ногу. Тут только композиция. Только составные объекты
Я очень рад критике и замечаниям! Спасибо!
показать ответы
Автор поста оценил этот комментарий

А по поводу наследования я осмелюсь возразить. Потому что наследование ломается, когда в игре появляется глубина. Когда куча юнитов с абсолютно разным поведением. Одни умеют ходить, другие - нет. Одни умеют бить, другие - нет. Одни бьют, другие стреляют, третьи заклинания кастуют, а четвертые могут только лечить, а пятые только строить. А супер юнит умеет делать это все сразу. А составные враги, когда платформа движется, а несколько пушек на ней по своей логике поражают разные типа целей. Выбрав наследование сразу стреляешь себе в ногу. Тут только композиция. Только составные объекты

Правильно приготовленное наследование и интерфейсы и созданы для решения таких проблем.

раскрыть ветку (1)
1
Автор поста оценил этот комментарий

Останусь при своем мнении. Потому что при использовании наследования и интерфейсов в таких кейсах скорее всего получится очень сложная иерархия классов. И либо там будет очень сложная структура, либо будет много дублирования кода, потому что не все классы получится привести к общему дереву, из-за чего может возникнуть ситуация, что разные типы юнитов не смогут обрабатываться единым образом.
Число возможных комбинаций «способность ходить/не ходить», «бить/стрелять/лечить/строить» растёт комбинаторно, и если пытаться их отразить классами — иерархия сразу же разрастётся до сотен классов (WalkerShooter, WalkerCaster, TowerBuilder, …).

Любая новая способность потребует либо введения нового уровня наследования, либо кардинальной переделки существующих веток.

Преимущества композиции:

- У каждой сущности есть минимальный «скелет»: ID, Transform, жизненный цикл, базовые методы

- Способности инкапсулируются в отдельных компонентах

• MovementComponent (или IMovable + WalkMovement, FlyMovement…)

• AttackComponent (MeleeAttack, RangedAttack, SpellAttack…)

• BuildComponent, HealComponent и т. п.

- При создании нужного юнита вы просто «собираете» набор компонентов. Никакого взрыва классов‑комбинаций.


Динамическая гибкость:

- Можно менять поведение «на лету» — добавить/убрать компонент, сменить стратегию атаки.

- Для «супер‑юнита» с 5‑ю видами атак достаточно зарегистрировать 5 разных AttackComponent’ов.

- Для «составных врагов» (движущаяся платформа + пушки) у вас будет две сущности: Platform + несколько Gun, у каждой Gun свой TargetingComponent и FireComponent, связанный с платформой.


SOLID и поддерживаемость:

- Композиция лучше ложится на принцип единственной ответственности (SRP) — каждый компонент отвечает за свою узкую задачу.

- OCP (Open/Closed): новые типы атак или передвижения добавляются без правок в уже существующие классы.

- Liskov (LSP) и ромбовидная наследственность в сложных иерархиях вас не побеспокоят.

А наследование лучше оставить для действительно «жёстких» is‑a связей, где один класс логически является подтипом другого и мы переиспользуем массу одинаковой логики.

Автор поста оценил этот комментарий

Да что вы находите в этом ECS. Это же сплошное спагетти.

раскрыть ветку (1)
1
Автор поста оценил этот комментарий
Технически это не ecs, а полноценное ООП под соусом data driven design. Т.е. я на полную использую принципы solid и паттерны, что позволяет максимально сократить количество спагетти, лапши и прочих макаронных изделий в коде. В чистовом коде, разумеется. В черновиках говнище, как обычно)
А почему выбирают ddd в играх? Да потому что система ориентированная на данные очень гибкая и хорошо подходит для разработки игр. Программисты описывают логику игрового мира в системах или других логических единицах, а гейм дизайнеры играются с конфигами и могут делать разные интересные штуки просто комбинируя компоненты.
показать ответы