-
Как бы вы реализовали абстрактный механизм способностей персонажей?
-
Какие ключевые классы и интерфейсы выделили бы?
-
Каким способом добились бы гибкой настройки со стороный гейм дизайн отдела и минимизировали вмешательство отдела разработки в создание новых вариаций способоностей? В качестве примера можно описать реализацию способности "Исцеление""Массовое исцеление" и способности "Нанесение урона""Массовое нанесение урона"?
Информация о скиллах может храниться как локально (см. Scripts/Base/ScriptableObject), так и на сервере(см. Scripts/Network).
В этом проекте рассмотрим оба случая.
-Для локального хранения/редактирования используем ScriptableObject и Sirenix Odin Inspector
-Для получения информации о скиллах с сервера используем UnityWebRequest, UniTask, Newtonsoft.Json
Затронем следующие пункты:
-Класс Unit и класс UnitSkill
-Локальное хранилище способностей
-Локальное хранилище персонажей
-Получение информации из БД сервера с помощью REST API
-Локатор сервисов
-Интерфейсы
-Скрипты персонажа
-Тест
В начале создадим класс Unit, который содержит имя (Warrior, Wizzard) и коллекцию скиллов
Далее создадим класс UnitSkill, который включает в себя:
-название скилла (Heal, MassHeal, Damage, MassDamage)
-тип (InstantUse, RadiusAroundUnit, Throw, MelleHit)
-описание (SkillNameText, SkillDescriptionText, SkillImageByteCode)
-использование (SkillUseCost, SkillCooldownMsec)
-зона поражения (SkillMaxThrowDistance, SkillThrowPower, SkillZoneRadius)
-воздействие на персонажей (ImpactHealthPoints, ImpactSpeedPoints, ImpactDurationMsec, ImpactFX)
Подробнее см. в проекте Scripts/Base/Class/ClassUnit.cs
Чтобы визуализировать класс скиллов, создадим класс LocalUnitSkills и наследуем от ScriptableObject:
Далее в инспекторе можно создать и гибко настроить несколько его экземпляров:
Heal
Mass Heal
Damage
Mass Damage (в данном случае - заморозка персонажей)
Путь до локального хранилища скиллов: ScriptableObjects/Unit
По аналогии создадим ScriptableObject для персонажей
И закрепим за ними подходящие скиллы:
Путь до локального хранилища персонажей аналогичный: ScriptableObjects/Unit
Таким образом персонажей и способности из локального хранилища можно легко создавать и редактировать любому человеку, не разбирающемуся в коде.
Теперь мы можем легко редактировать параметры скиллов персонажей и создавать новые вариации способоностей. Однако информация о скиллах все еще находится в Unity и зависит от сборки.
При наличии сервера лучше создать в нем базу данных скиллов и получать ее по REST API перед каждым запуском игры. Редактируя записи в конфигурации на сервере, можно изменять параметры игры в любое время и не беспокоить пользователей необходимостью обновлять приложение, чтобы получить актуальную версию скиллов.
Для этого создадим скрипт WebRequest, который будет отправлять GET запрос на потенциальный сервер через UnityWebRequest (см. Scripts/Network/WebRequest.cs)
Далее создадим надстройку WebRequestUnit.cs и метод GET_UnitSkills, который будет формировать конкретный запрос для скиллов, получать респонс с сервера, а затем десериализировать его с помощью Newtonsoft.Json.JsonConvert:
Создадим ScriptableObject, который будет хранить путь к серверным запросам (для навигации в серверных запросах можно воспользоваться Swagger UI)
Путь до хранилища серверных запросов:
Если на сервере есть админ-панель, можно подключить к ней интерфейс создания/редактирования скиллов и персонажей для того, чтобы они были доступны для людей, не разбирающихся в коде проекта.
Теперь мы имеем возможность получать информацию о скиллах как локально, так и с помощью сервера.
Чтобы обращаться к ней из любых скриптов проекта, создадим ServiceLocatior.cs, сделаем из него static singleton
Cоздаем скрипты, которые будут хранить ссылки на инструменты работы с серверными запросами, а так же с локальной БД персонажей и их способностей:
Чтобы была возможность обратиться к этим скриптам, они должны быть дочерними для gameObject с нашим компонентом ServiceLocator.cs. Далее в нем напишем метод получения дочерних объектов по их типу:
Теперь мы можем обратиться к информации о скиллах из любого интересующего нас места через ServiceLocator.
Для масштабных проектов вместо ServiceLocatior лучше использовать фреймворк Zenject - он более гибкий в использовнии.
Так же для удобства создадим интерфейсы, которые будут отвечать за здоровье/скорость/эффекты/скиллы персонажа:
Например, здоровье персонажа:
Пример использования:
Приступим к генерации героев и скиллов. Для этого создадим скрипт UnitList.cs, в котором можно выбрать тип получения скиллов - с помощью локальной базы данных ScriptableObject или через RestApi. Для этого используем переключатель UseRestApi
Когда экземляр персонажа создан, добавим и инциализируем его игровые компоненты (Health, Skills, Speed, VisualEffect, Impact):
Рассмотрим UnitSkills.cs подробнее. На старте мы получаем скиллы с помощью ServiceLocator, либо из базы данных сервера через запрос из WebRequestUnit, либо через локальную базу данных через запрос из UnitLocalSource
Получив информацию о скиллах, мы можем провести небольшой тест:
В зависимости от типа скилла можно выбрать нужный компонент персонажа. Если это граната - создаем компонент, отвечающий за метание гранат. Если это зона урона/лечения - создаем компонент, отвечающий за создание вокруг персонажа окружности с соответствующим импактом, и т.д.
В папке проекта ScriptableObjects/Unit хранятся данные о способностях, которые можно добавлять/убирать/редактировать
Запустим проект и проверим консоль:
Eсли имеется сервер с готовыми скиллами и вы хотите получить их через Rest API, тогда поставьте галочку UseRestApi в скрипте UnitList.cs
Заполните URL и токен в запросе WebRequestUnit.cs
И укажите URL адреса запросов в UrlUnit из папки ScriptableObjects/Swagger Url:
Больше проектов можно найти на моей сайте https://playstel.com/