Перейти к основному содержимому

Настройте своё первое сражение

Это руководство покажет, как настроить зону встреч, запустить дикое сражение и понять ход сражения. К концу у вас будет работающее сражение, которое можно протестировать в редакторе.

Готовый результат

Вот к чему вы идёте: дикая встреча, которая запускается с тайла травы, с меню из четырёх действий и соперником, выбранным таблицей встреч.

Предварительные требования​

  • MCE установлен, и мастер настройки пройден.
  • В вашей базе данных есть хотя бы один монстр (из демо-проекта или созданный вами).
  • У вас есть сцена с персонажем-игроком и тайлмапом на сетке, а также ассет SceneInfo для этой карты.

Шаг 1: Создайте зону встреч​

Дикие сражения запускаются тайлами встреч на вашем тайлмапе. Тайл встречи — это обычный тайл, префаб которого содержит компонент EncounterTile; у компонента единственная настройка, Encounter Type, которая определяет, какой вид встречи запускает тайл: Grass, Water, Surfing, Cave, FishingOldRod, FishingGoodRod, FishingSuperRod, Diving, RockSmash, HeadButt, BugContest или Other.

  1. Используйте префаб тайла встречи — движок поставляется с готовыми, например Assets/OpenMon/Game/Prefabs/World/Water/Water/WaterEncounterTile.prefab, — или сделайте свой: создайте префаб, добавьте компонент EncounterTile и выберите его Encounter Type.
  2. Сделайте этот префаб GameObject тайла-ассета и нарисуйте тайл на слое тайлмапа, где должны появляться дикие монстры (обычно это слой «Grass»).

Каждый шаг игрока на такой тайл проверяется по шансу встречи. В сцене, SceneInfo которой помечена как подземелье, каждый пройденный тайл считается встречей Cave без необходимости рисовать тайлы.

Шаг 2: Настройте таблицу встреч​

В траве живёт ScriptableObject WildEncountersSet, а SceneInfo карты решает, какой набор отвечает за какой тип встречи. Создайте набор:

  1. Assets > Create > MCE > Battle > Encounters > WildEncountersSet (или кнопка New Wild Encounter Set на вкладке Database в Hub).
  2. Дайте ему описательное имя, например Route1_GrassEncounters.
  3. Заполните его три списка:
СписокЗначение
Base EncountersМонстры, которые появляются всегда
Encounters Per MomentДополнительные монстры для времени суток: Night, Dawn, Day или Dusk
Encounters Per WeatherДополнительные монстры при определённой погоде вне сражения

Каждая запись — это WildEncounter:

ПолеОписание
MonsterMonsterEntry, который может появиться
Form CalculatorАссет, выбирающий форму (SingleFormEncounter всегда возвращает одну форму)
Min Level / Max LevelДиапазон уровней дикого монстра (1–100; максимум не может быть ниже минимума)
WeightОтносительный шанс этой записи (больше = чаще)

Например:

МонстрДиапазон уровнейВес
Flameleon3-540
Leaflet3-540
Sparkit4-620
  1. Откройте ассет SceneInfo вашей карты и в его группе Encounters добавьте запись для типа встречи (например, Grass) и назначьте ваш WildEncountersSet. Без этой записи на карте нет диких монстров для этого типа.

Шаг 3: Настройте сцену сражения​

MCE использует отдельную сцену сражения, которая загружается аддитивно поверх мира при начале сражения. Вам нужны:

  1. Ассет BattleLauncher. Это ScriptableObject (Create > MCE > Battle > Launcher), привязанный через BattleLauncherInstaller, а не компонент вашей сцены. Его поле Battle Scene указывает на сцену сражения, а сам он содержит списки боевой музыки. Настройка проекта уже включает один такой.
  2. Сцена сражения в настройках сборки. Сцена по умолчанию (Battle.unity в Assets/OpenMon/Core/Game/Scenes/) входит в состав MCE.

BattleLauncher управляет переходом:

  • Строит объект BattleParameters (тип сражения, тип противника, команды, персонажи, сценарий, погода).
  • Загружает сцену сражения аддитивно.
  • Передаёт параметры BattleManager в этой сцене.
  • Выгружает сцену и возвращается в мир, когда сражение заканчивается.

Компоненты BattleManager​

BattleManager — сердце боевой системы. В сцене сражения вы найдёте GameObject с компонентом BattleManager. Ему требуются пятнадцать модулей рядом, каждый — MonoBehaviour на том же GameObject, плюс BattleStateMachine:

МодульНазначение
BattleManagerBattlersModuleПоиск бойцов на обеих сторонах, спрайты, формы, бегство
BattleManagerHealthModuleИзменения HP, обнаружение и обработка потери сознания
BattleManagerMovesModuleВыполнение приёмов, точность
BattleManagerItemsModuleИспользование предметов в сражении
BattleManagerCaptureModuleМеханика поимки диких монстров
BattleManagerAIModuleПринятие решений противником
BattleManagerAnimationModuleВступление сражения и анимации хода
BattleManagerAudioModuleМузыка и звуковые эффекты сражения
BattleManagerStatusesModuleСтатусные состояния (ожог, яд, сон и т. д.)
BattleManagerBattlerStatsModuleСтупени характеристик и их изменения
BattleManagerBattlerSwitchModuleВыпуск и отзыв бойцов
BattleManagerRostersModuleУправление командой во время сражения
BattleManagerScenariosModuleПогода, местность и настройка сценария
BattleManagerMegaModuleМега-эволюция
BattleManagerCharactersModuleПерсонажи-тренеры

Настраивать их по отдельности не нужно. Каждый модуль обращается к соседям через BattleManager, а остальная связка обеспечивается внедрением зависимостей Zenject.

Шаг 4: Узнайте цикл сражения​

BattleStateMachine ведёт сражение как один цикл, который повторяется каждый ход до конца сражения:

Update fought battlers → Request actions (player menu / AI) →
→ Determine action order → Perform actions →
→ End-of-turn callbacks and status countdown →
→ Check and process fainted battlers → [next turn]
... until IsBattleOver → end animation, prize/defeat money, end callbacks

Цикл — часть префаба сражения; его не нужно настраивать. Чтобы понять или изменить его, см. Внутреннее устройство сражений.

Шаг 5: Протестируйте сражение​

  1. Убедитесь, что в вашей сцене мира есть:

    • PlayerCharacter с командой, содержащей хотя бы одного монстра.
    • Тайлы встреч, нарисованные на тайлмапе.
    • SceneInfo, запись Encounters которой для этого типа указывает на настроенный WildEncountersSet.
  2. Нажмите Play в редакторе.

  3. Проведите персонажа по тайлам встреч.

  4. Через несколько шагов (определяется шансом встречи) запустится сражение.

Быстрое тестирование

Шанс на шаг берётся из таблицы TileEncounterChance вашего ассета MCESettings (одно значение на тип встречи), если только SceneInfo карты не определяет собственный шанс для этого типа. Чтобы тестировать сражения сразу, не бродя по карте, задайте шанс тестируемого типа равным 1 (100 %).

Понимание хода сражения​

Когда начинается сражение, под капотом происходит следующее:

  1. Игрок наступает на EncounterTile; шаг проверяется по шансу для этого Encounter Type.
  2. Соответствующий WildEncountersSet карты выдаёт возможные встречи для текущего времени суток и погоды; одна выбирается по весу, а уровень выбирается из её диапазона.
  3. Создаётся объект BattleParameters с данными дикого монстра, и BattleLauncher загружает сцену сражения аддитивно.
  4. BattleManager инициализирует все модули.
  5. Проигрывается вступление сражения.
  6. Игроку предлагаются действия: Fight, Bag, Monster, Run.
  7. Действия выполняются в порядке приоритета и скорости.
  8. Цикл продолжается, пока одна сторона не потеряет сознание или игрок не убежит/не поймает монстра.
  9. BattleResultParameters возвращаются в мир (кто победил, пойманный монстр, флаг возрождения).
  10. Сцена сражения выгружается, и мир продолжается.

Типы сражений​

Два перечисления описывают, чем является сражение:

ПеречислениеЗначенияЗначение
BattleTypeSingleBattle, DoubleBattleОдин монстр с каждой стороны или два
EnemyTypeWild, TrainerДикий монстр (можно поймать) или NPC-тренер (поймать нельзя, платит призовые)

Оба передаются в BattleParameters и доступны в BattleManager.

Подписка на события сражения​

Реагируйте на события сражения, не привязывая свой игровой код к внутренностям. Лаунчер сражений привязан в системе внедрения зависимостей, поэтому на него может подписаться любой скрипт:

using OpenMon.MCE.Battle;

public class MyBattleTracker : MonoBehaviour
{
[Inject] private IBattleLauncher battleLauncher;

private void OnEnable()
{
battleLauncher.SubscribeToBattleLaunched(HandleBattleLaunched);
battleLauncher.SubscribeToBattleEnded(HandleBattleEnded);
}

private void OnDisable()
{
battleLauncher.UnsubscribeFromBattleLaunched(HandleBattleLaunched);
battleLauncher.UnsubscribeFromBattleEnded(HandleBattleEnded);
}

private void HandleBattleLaunched()
{
Debug.Log("A battle has been launched!");
}

private void HandleBattleEnded(BattleResultParameters result)
{
Debug.Log($"Battle ended. Player won: {result.PlayerWon}");
}
}

battleLauncher.BattleInProgress сообщает, идёт ли сражение. SDK также предлагает IBattleSystem (engine.Battle) с OnBattleStarted и OnBattleEnded, но его хуки в движке пока не подключены; см. Руководство по публичному API и IBattleSystem.

Устранение неполадок​

ПроблемаРешение
Сражение не запускаетсяПроверьте, что у тайла есть EncounterTile с нужным Encounter Type, что в SceneInfo карты есть WildEncountersSet для этого типа и что в TileEncounterChance есть значение для него (отсутствующий тип считается равным 0 и один раз пишет предупреждение)
Чёрный экран после встречиУбедитесь, что сцена сражения есть в списке сцен Build Settings и указана в BattleLauncher
Монстр появляется на уровне 0Убедитесь, что Min Level и Max Level заданы в записи встречи
Нет боевой музыкиПроверьте, что в BattleLauncher есть музыка в списках диких/тренерских сражений и что в BattleManagerAudioModule назначено аудио
Вылеты при начале сраженияОткройте OpenMon Hub → вкладка Database → Validate Database, чтобы найти отсутствующие ссылки базы данных

Следующие шаги​