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

Система движения по сетке

MCE использует систему движения по тайловой сетке, построенную на Tilemap Unity. Игрок и NPC перемещаются по одному тайлу за раз по дискретной сетке, а обнаружение столкновений, эффекты местности и переходы между картами обрабатывает система сетки.

Как разрешается шаг

Сетка в игре

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

Основные компоненты​

GridController​

GridController — менеджер тайловой сетки для каждой сцены. Он находится на том же GameObject, что и Grid Unity (требует его), и:

  • Находит Tilemap сцены и отвечает на запросы о тайлах по всем ним — от наивысшего порядка сортировки к низшему.
  • Читает тип движения каждого тайла из ассета TileData проекта (см. Пользовательские типы тайлов).
  • Отслеживает персонажей и акторов, зарегистрированных в сетке.
  • Хранит SceneInfo сцены (см. ниже).
  • Отвечает на запросы о столкновениях: может ли персонаж переместиться на этот тайл, с этого тайла?

В каждой сцене карты один GridController в корне её сетки.

MCECharacterController​

MCECharacterController управляет движением любого персонажа (игрока, NPC или монстра) по сетке:

  • Движение с привязкой к сетке: персонажи перемещаются ровно на один тайл за шаг.
  • Движение в 4 направлениях: вверх, вниз, влево, вправо. Без диагонального движения.
  • Отрисовка спрайта: обновляет направление спрайта и анимацию ходьбы.
  • Проверка столкновений: перед каждым перемещением запрашивает GridController.
  • Скорость движения: Speed, в секундах на тайл (по умолчанию 0,25).

PlayerCharacter​

PlayerCharacter добавляет поверх контроллера возможности, специфичные для игрока:

  • Обработка ввода (клавиатура и геймпад).
  • Триггеры взаимодействия (нажатие кнопки действия лицом к NPC/объекту).
  • Обработка диких встреч, шаги репеллента и счётчик шагов (GlobalGameData.StepsTaken, который также управляет циклами яиц и дружбой).
  • Бег, езда на велосипеде и плавание.
  • Координация монстра-последователя и горячие клавиши эмоций.

GlobalGridManager​

GlobalGridManager отвечает за навигацию между картами:

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

Типы тайлов​

У каждого ассета тайла есть тип движения (TileType), назначаемый в ассете TileData:

TileTypeОписание
NonExistentУ тайла нет данных; считается пустотой
WalkableОбычная земля
NonWalkableТвёрдое препятствие (стены, деревья, камни)
JumpableУступ: преодолевается прыжком в одном направлении
BridgeПоверхность моста, расположенная выше того, что под ней
BridgeEntranceПереходный тайл между землёй и мостом
WaterВода, которую нужно пересекать вплавь
WaterfallВертикальная вода, по которой можно подняться
SlipperyЛёд: персонаж скользит, пока не упрётся в препятствие
WalkableNotBikableПроходим пешком, но не на велосипеде

Поверх типа поведения тайлов (компоненты на префабе тайла) добавляют логику: EncounterTile отмечает зону диких встреч, OneWayJumpableTile задаёт направление уступа, ForceCharacterToKeepMoving создаёт конвейеры и течения, а также TallGrass, LadderUp, WaterfallEdge, WhirlwindInDirection и другие. Все они описаны в разделе Пользовательские типы тайлов.

Настройка карты​

Шаг 1: Создайте структуру Tilemap​

Карты MCE используют стандартную иерархию Tilemap Unity:

Grid (Grid + GridController)
└── Ground (Tilemap, TilemapRenderer, sorting order 0)
└── GroundOverlay (Tilemap, TilemapRenderer, sorting order 1)
└── Above ... (more Tilemaps as needed)
└── Actors (NPC GameObjects)

Отдельного тайлмапа столкновений рисовать не нужно: движение блокирует TileType тайлов, которые вы нарисовали.

Шаг 2: Нарисуйте карту​

Используйте оверлей Редактора карт или Tile Palette Unity (Window > 2D > Tile Palette), чтобы нарисовать карту:

  1. Слой Ground: базовая местность (тропы, трава, земля, берега воды).
  2. Слои оверлея: украшения поверх земли (цветы, камни, тени) и то, что рисуется поверх игрока (кроны деревьев).
  3. Тайлы встреч: тайлы, префаб которых несёт EncounterTile, где появляются дикие монстры.

Шаг 3: Добавьте GridController​

  1. Выберите корневой GameObject Grid.
  2. Добавьте компонент GridController.
  3. Контроллер получает ассет TileData проекта через внедрение зависимостей; убедитесь, что каждый нарисованный вами тайл зарегистрирован там с правильным TileType (помогают кнопки Populate и CheckInvalid ассета). Незарегистрированный тайл считается проходимым и пишет предупреждение.

Шаг 4: Настройте SceneInfo​

Каждой сцене карты нужен компонент SceneInfo, указывающий на SceneInfoAsset (создаётся кнопкой New Scene Info на вкладке Database в Hub). Назначьте компонент в поле Scene Info у GridController. Ассет содержит:

ПолеОписание
SceneСцена, которую описывает эта информация
Localizable Name KeyОтображаемое название места (показывается в заголовке)
Neighbours / Neighbour OffsetsКарты, соединяющиеся с этой, и их положение в тайлах (бесшовные переходы)
Background MusicМузыка этой карты
Is Affected By Sky, Default Weather, Allowed WeathersДневной/ночной свет и погода
Can Open Storage Here, Can Fly From Here, Can Teleport From Here, Can Escape Rope From Here, Can Fish HereЧто игрок может делать здесь
Is Dungeon, Is DarkКарта-подземелье использует встречи Cave на каждом тайле
Region, TagsРегион и теги сцены, используемые игровой логикой (например, «Cave», «Town», «Route»)
Encounters, Battle Scenarios Per Encounter, Own Encounter ChancesДикие встречи карты: см. Дикие встречи

Особая местность​

Мосты​

Мосты позволяют персонажу идти по тайлам, которые иначе были бы непроходимы (например, по воде):

  1. Используйте для моста слой тайлмапа с более высоким порядком сортировки.
  2. Задайте тайлам моста тип Bridge, а тайлам, где на него вступают, — BridgeEntrance.
  3. Персонаж идёт по слою моста, когда вступает на него.

Логика моста отвечает за порядок по Z: персонаж отображается выше воды, но ниже перил моста (OverBridgeBodySortOrder).

Скользкие тайлы (лёд)​

На ледяных тайлах персонаж скользит в направлении движения, пока не упрётся в стену или тайл без льда:

  1. Задайте ледяным тайлам тип Slippery.
  2. MCECharacterController переопределяет ввод и продолжает движение в том же направлении.
  3. Добавляйте стены или препятствия, чтобы создавать ледяные головоломки.

Уступы​

Уступы — односторонние тайлы: персонаж может спрыгнуть вниз, но не может вскарабкаться обратно:

  1. Задайте тайлу тип Jumpable и добавьте к его префабу поведение OneWayJumpableTile.
  2. Задайте его Jump Direction.
  3. Когда персонаж пересекает уступ, проигрывается анимация прыжка.

Водопады​

По водопадам можно подниматься с подходящей способностью:

  1. Задайте тайлам водопада тип Waterfall (для края можно использовать WaterfallEdge).
  2. Когда игрок стоит лицом к водопаду и применяет способность подъёма, персонаж поднимается.

Переходы между картами​

Бесшовные соединения​

Для карт, соединённых напрямую (Маршрут 1 продолжается в Маршрут 2 на северном краю), перечислите каждую карту в Neighbours другой, указав Neighbour Offsets в тайлах, которые её размещают. GlobalGridManager аддитивно загружает соседей, и персонаж просто переходит из одной сетки в другую: когда в текущей сетке нет тайла в целевой позиции, менеджер ищет загруженную сетку, где он есть. Тайл соседа, который является стеной (NonWalkable) или пустотой (NonExistent), по-прежнему блокирует шаг.

Варпы (двери, пещеры, телепорты)​

Чтобы переместить игрока в другое место:

  1. Поместите TriggerActor на тайл двери или входа (TriggerActor не блокирует движение и запускает граф, когда игрок на него вступает).
  2. В его CommandGraph добавьте узел TeleportPlayer, указав пункт назначения как место сцены (целевой SceneInfoAsset и тайл). При игре онлайн сервер сначала проверяет телепорт.
  3. По желанию добавьте вокруг него OpenDoor, FadeScreenToBlack и звуки, чтобы оформить переход.

У импортированных карт варпы расставляет интеграция сцен импортёра.

Настройка движения игрока​

Скорость движения — поле Speed персонажа, в секундах на тайл (по умолчанию 0,25, то есть четыре тайла в секунду). Состояние персонажа масштабирует время на тайл:

СостояниеМножитель времени на тайл
Ходьба1
Бег (IsRunning)0,33
Велосипед (IsBiking)0,15
Плавание (IsSwimming)0,66
Прыжокпрыжок проигрывается за 1,5x времени шага

Счётчик шагов (GlobalGameData.StepsTaken) увеличивается с каждым шагом и управляет циклами яиц и тиками дружбы.

Монстры-последователи​

MCE поддерживает систему последователей, при которой первый монстр в команде игрока идёт за ним по миру:

  • MonsterFollowerController управляет позицией и спрайтом последователя.
  • Последователь остаётся на один тайл позади игрока и догоняет его после кат-сцен.
  • Спрайты последователей настраиваются по виду и форме в MonsterEntry (поля WorldIdleSprite* и WorldWalkingSprite*).
  • Игрок может взаимодействовать с последователем (повернуться к нему и нажать кнопку действия), чтобы увидеть реакцию; импортированная игра может принести собственную таблицу реплик, а последователь может показывать эмоциональные шарики.
Спрайты последователей

Если у вида монстра не назначен спрайт последователя для мира, последователь не появится. Создайте листы спрайтов последователей вручную как листы цикла ходьбы на 4 направления.

Рекомендации​

  1. Сохраняйте согласованность типов тайлов. Регистрируйте каждый нарисованный тайл в TileData и используйте один и тот же тип для одного вида местности.
  2. Проверяйте варпы в обе стороны. Убедитесь, что можно пройти из A в B и обратно из B в A.
  3. Используйте теги сцен для логики. Вместо жёсткого задания названий карт помечайте карты как «Cave», «Water», «Forest» и т. д.
  4. Оптимизируйте большие карты. Очень большие тайлмапы могут влиять на производительность. Рассмотрите разделение на несколько соединённых сцен с помощью Neighbours.
  5. Тестируйте с геймпадом. Движение по сетке должно быть отзывчивым как на клавиатуре, так и на контроллере.