Создание 3D Пакмана в Unity пошагово

Как сделать пакмана на юнити 3д

Содержание статьи

Как сделать пакмана на юнити 3д

Классический Pac-Man – идеальный проект для изучения основ 3D-разработки в Unity. В этой статье мы создадим упрощённую трёхмерную версию игры с нуля, используя встроенные инструменты движка: ProBuilder для быстрого моделирования лабиринта, NavMesh для навигации призраков и C#-скрипты для управления логикой. Рассмотрим оптимальные подходы к структуре проекта, чтобы избежать типичных ошибок новичков: жёстко закодированных координат, неэффективных коллайдеров и проблем с производительностью при большом количестве объектов.

Начнём с подготовки сцены: создадим лабиринт размером 20×20 юнитов с высотой стен 3 юнита, используя примитивы ProBuilder. Для текстурирования применим стандартный материал Unity с UV-развёрткой, чтобы избежать растяжения текстур на углах. Игровой персонаж – сфера радиусом 0.5 юнита с компонентом Rigidbody и скриптом движения, обрабатывающим ввод с клавиатуры через Input.GetAxis. Скорость перемещения зададим в 5 юнитов/сек, а для плавного поворота используем Quaternion.Slerp с коэффициентом 0.1f.

Призраки реализуем как капсулы с компонентом NavMeshAgent, который автоматически прокладывает путь к игроку. Для генерации NavMesh экспортируем лабиринт в .obj, затем импортируем обратно и выпекаем навигационную сетку с параметрами: Agent Radius = 0.4, Step Height = 0.3. Логику преследования разделим на три состояния: патрулирование (случайное движение по точкам), погоня (преследование игрока) и испуг (бегство при съедании энерджайзера). Переключение состояний будем обрабатывать через конечный автомат на основе ScriptableObject, чтобы упростить расширение поведения.

Сбор точек и энерджайзеров реализуем через триггерные коллайдеры: при столкновении с объектом типа Collectible вызываем метод OnTriggerEnter, который удаляет объект и обновляет счётчик. Для оптимизации производительности используем Object Pooling – заранее создадим 50 точек и будем активировать/деактивировать их по мере необходимости. Звуковые эффекты добавим через AudioSource с параметрами Spatial Blend = 1 и Min Distance = 1, чтобы звук затухал с расстоянием. В конце настроим камеру с Cinemachine, задав Body = Framing Transposer и Dead Zone Width = 0.1 для плавного следования за игроком.

Настройка проекта и импорт базовых ассетов

Настройка проекта и импорт базовых ассетов

После открытия проекта перейдите в Edit > Project Settings > Player и установите Color Space на Linear. Это улучшит качество рендеринга, особенно для ярких цветов, характерных для Пакмана. В разделе Scripting Define Symbols добавьте UNITY_POST_PROCESSING_STACK_V2, если планируете использовать постобработку для эффектов вроде свечения.

Импортируйте базовые ассеты через Asset Store или локальные файлы. Для начала скачайте бесплатный пакет Standard Assets от Unity – в нём есть готовые материалы, текстуры и префабы для прототипирования. Альтернативно используйте Kenney’s Game Assets (набор 3D Platformer Pack), где есть модели стен, пола и простых врагов, подходящие по стилю.

Создайте структуру папок в Assets: Models, Materials, Scripts, Prefabs, Scenes и Textures. В папку Models поместите FBX-файлы с низкополигональными моделями Пакмана, призраков и лабиринта. Для экономии ресурсов убедитесь, что полигонов в моделях не более 500 на объект – этого достаточно для ретро-стиля.

Настройте материалы для каждого объекта. Для Пакмана используйте Standard Shader с параметром Metallic = 0 и Smoothness = 0.3, чтобы добиться матового пластикового вида. Призракам назначьте полупрозрачный материал с Transparent рендерингом и альфа-каналом в текстуре. Лабиринт покройте материалом с текстурой кирпичной стены (разрешение 1024×1024) и Tiling = 2 для повторяемости.

Создайте префабы для всех игровых объектов. Перетащите модели в сцену, настройте коллайдеры (Box Collider для стен, Sphere Collider для Пакмана) и сохраните как префабы в папке Prefabs. Для призраков добавьте компонент Rigidbody с Is Kinematic = true, чтобы они двигались через скрипты, а не физику. Проверьте масштаб объектов – стандартный размер Пакмана должен быть 1x1x1 юнита.

Создание игрового поля с лабиринтом и стенами

Создание игрового поля с лабиринтом и стенами

Начните с импорта 3D-модели лабиринта или создайте его вручную в Unity. Используйте ProBuilder (встроенный инструмент Unity) для быстрого прототипирования стен и коридоров. Задайте размеры поля: стандартный лабиринт для Пакмана – 28×31 ячеек, где каждая ячейка равна 1×1 юниту. Это упростит расстановку объектов и навигацию.

Создайте пустой GameObject с именем Maze и сделайте его родителем для всех элементов лабиринта. Для стен используйте кубы (GameObject > 3D Object > Cube) с масштабом (1, 2, 1) – высота 2 юнита обеспечит перекрытие камеры и предотвратит «выпадение» Пакмана за пределы поля. Примените материал с текстурой кирпича или однотонным цветом для визуальной четкости.

  • Размещайте стены по границам ячеек, оставляя проходы шириной 1 юнит.
  • Для угловых элементов используйте поворот на 45° и масштабирование по оси Z до 1.41 (√2) для сохранения пропорций.
  • Избегайте пересечений стен – это вызовет баги в коллизиях.

Оптимизируйте коллайдеры: замените Box Collider на Mesh Collider для сложных участков лабиринта, но оставьте простые кубы с Box Collider для прямых стен. Включите Convex для Mesh Collider, если стена не вогнутая. Для экономии ресурсов объедините соседние стены в один меш с помощью Mesh Combine Studio или скрипта объединения мешей.

Добавьте точки спавна для точек и призраков. Создайте пустые GameObject с тегами DotSpawn и GhostSpawn, разместив их в центре ячеек. Используйте скрипт для автоматического заполнения поля точками:

public GameObject dotPrefab;
public Transform mazeParent;
public Vector2Int gridSize = new Vector2Int(28, 31);
void Start() {
for (int x = 0; x < gridSize.x; x++) {
for (int y = 0; y < gridSize.y; y++) {
if (!Physics.CheckSphere(new Vector3(x, 0.5f, y), 0.4f)) {
Instantiate(dotPrefab, new Vector3(x, 0.5f, y), Quaternion.identity, mazeParent);
}
}
}
}

Для телепортов создайте два пустых GameObject с коллайдерами-триггерами на границах лабиринта. Назначьте им скрипт:

public Transform teleportTarget;
void OnTriggerEnter(Collider other) {
if (other.CompareTag("Player")) {
other.transform.position = teleportTarget.position;
}
}

Проверьте лабиринт на ошибки: запустите игру и протестируйте прохождение Пакмана по всем маршрутам. Используйте Debug.DrawRay для визуализации лучей столкновений в редакторе. Экспортируйте лабиринт как префаб для повторного использования в других сценах.

Моделирование и анимация главного персонажа Пакмана

Моделирование и анимация главного персонажа Пакмана

Начните с создания базовой геометрии Пакмана в Blender или Maya: используйте сферу с вырезанным сектором в 60 градусов для рта. Оптимальный радиус – 0.5 единиц Unity, чтобы персонаж корректно вписывался в стандартные размеры игровых объектов. Экспортируйте модель в формате FBX с включёнными нормалями и UV-развёрткой, избегая масштабирования при импорте в Unity (Scale Factor = 1).

Для анимации рта создайте два ключевых кадра: закрытый (сектор 60°) и открытый (сектор 120°). В Animation Window добавьте кривую анимации с параметром "MouthAngle" (тип float), связав её с углом выреза через скрипт. Длительность цикла – 0.3 секунды, частота кадров – 30 FPS. Используйте Animation Curve для плавного перехода между состояниями с Ease In/Out.

Добавьте материал с шейдером Unlit/Color для равномерного освещения без теней. Цвет – #FFE600 (жёлтый Пакмана), параметр Rendering Mode установите в "Opaque". Для глаз создайте отдельные меши (сферы радиусом 0.05) с материалом Standard Shader и металлическим отражением (Metallic = 0.8, Smoothness = 0.9). Разместите их на расстоянии 0.3 единицы от центра головы.

Реализуйте анимацию движения через скрипт, изменяющий положение модели по оси Z с учётом скорости (например, 3 единицы/сек). Для поворотов используйте Quaternion.Slerp с коэффициентом 0.15 для сглаживания. В Animator Controller создайте параметр "Speed" (float) и свяжите его с Blend Tree для переключения между состояниями "Idle" и "Move" при значении > 0.1.

Для эффекта "мигания" добавьте второй слой анимации в Animator с весом 0.2. Создайте анимацию, уменьшающую масштаб глаз по оси Y до 0.1 на 0.1 секунды с интервалом 3–5 секунд. Управляйте этим через скрипт с Random.Range для случайного запуска триггера "Blink".

Оптимизируйте модель: объедините меши рта и глаз в один объект, уменьшите количество полигонов сферы до 128 сегментов. В импортере FBX установите Rig как "Humanoid" для совместимости с системой анимации Unity, даже если персонаж не использует скелет. Для коллизии добавьте компонент Capsule Collider с радиусом 0.45 и высотой 1.0, смещённый на 0.5 по оси Y.

Реализация движения призраков с алгоритмом преследования

Реализация движения призраков с алгоритмом преследования

Для реализации преследования Пакмана призраками используйте алгоритм A* (A-star) с модификациями для игрового поля. Создайте двумерный массив Grid, где каждая ячейка соответствует тайлу лабиринта. Задайте веса: проходимые тайлы – 1, стены – Mathf.Infinity, а бонусы (точки, фрукты) – 0.5 для стимуляции обхода опасных зон. Призраки должны пересчитывать путь каждые 0.3–0.5 секунды, чтобы избежать застревания и адаптироваться к движениям игрока.

Оптимизируйте поиск пути, ограничив область поиска радиусом в 15–20 тайлов от текущей позиции призрака. Используйте NavMesh для динамического обновления навигационной сетки, если лабиринт содержит движущиеся элементы. Для каждого призрака добавьте уникальный параметр aggression (0.1–1.0), влияющий на частоту перерасчета пути: агрессивные призраки обновляют маршрут чаще, но тратят больше ресурсов.

Реализуйте три режима поведения: преследование, разброс и испуг. В режиме преследования цель – позиция Пакмана, в режиме разброса – случайная точка на карте, а в испуге – точка, максимально удаленная от игрока. Переключайте режимы по таймеру или при сборе бонусов. Для испуга добавьте анимацию мерцания и увеличьте скорость на 20–30%, чтобы создать эффект паники.

Избегайте коллизий между призраками, добавив систему приоритетов: если два призрака претендуют на один тайл, право прохода получает тот, у кого выше aggression. Для плавного движения используйте Vector3.SmoothDamp с параметром smoothTime = 0.1–0.2. При столкновении со стеной призрак должен мгновенно пересчитать путь, а не скользить вдоль препятствия.

Тестируйте алгоритм на картах с узкими проходами и тупиками. Добавьте отладочную визуализацию пути с помощью Debug.DrawLine, чтобы отслеживать ошибки в навигации. Для повышения производительности кешируйте результаты поиска пути для повторяющихся целей и используйте пул объектов для временных узлов A*.

Добавление системы сбора точек и бонусов

Добавление системы сбора точек и бонусов

Создайте пустой GameObject с именем "PointManager" и прикрепите к нему скрипт C#. В скрипте объявите публичное статическое целочисленное поле `score` для хранения очков и событие `OnScoreChanged` для обновления UI через другие компоненты. Для точек используйте префаб сферы диаметром 0.3 единицы, материалом с самосвечением (Emission) и коллайдером типа Sphere. Размещайте точки в сцене через Instantiate в цикле, задавая позиции с шагом 1.5 единицы по осям X и Z в пределах игрового лабиринта.

Реализуйте обработку столкновений в скрипте игрока: при входе в триггер (OnTriggerEnter) проверяйте тег объекта. Для точек ("Point") увеличивайте `score` на 10, для бонусов ("Bonus") – на 50 и запускайте корутину исчезновения бонуса через 5 секунд. Уничтожайте объект точки методом Destroy(gameObject) и вызывайте событие `OnScoreChanged.Invoke()`. Для оптимизации используйте Object Pooling: создайте пул из 200 точек при старте игры и переиспользуйте их вместо постоянного создания/уничтожения.

Бонусы сделайте в виде вращающихся кубов с анимацией масштабирования (0.8–1.2) через LeanTween. Прикрепите к ним скрипт с публичным методом `ActivateBonus()`, который временно удваивает скорость игрока на 8 секунд. В скрипте игрока добавьте булево поле `isBonusActive` и модифицируйте скорость движения в методе Update: `moveSpeed = isBonusActive ? defaultSpeed * 2 : defaultSpeed`. Создайте отдельный скрипт для спавна бонусов, который каждые 15 секунд размещает один бонус в случайной точке лабиринта, проверяя отсутствие пересечений с другими объектами через Physics.OverlapSphere.

Для визуальной обратной связи добавьте к игроку Particle System с эффектом искр, который активируется при сборе бонуса. Настройте эмиттер на 30 частиц с размером 0.1, временем жизни 0.5 секунды и цветом градиента от желтого к оранжевому. В скрипте игрока запускайте систему частиц через `particleSystem.Play()` при вызове `ActivateBonus()`. Для звукового сопровождения используйте AudioSource с двумя клипами: короткий "pling" для точек (громкость 0.3) и более длинный "powerup" для бонусов (громкость 0.7).

Создайте скрипт "GameController" для управления прогрессом: при сборе всех точек (проверяйте через `GameObject.FindGameObjectsWithTag("Point").Length == 0`) загружайте сцену победы. Для отслеживания собранных бонусов используйте статическое поле `bonusCount` в PointManager. При достижении 3 бонусов активируйте дополнительный эффект – временную неуязвимость призраков: измените их материал на полупрозрачный синий и отключите их коллайдеры на 10 секунд через корутину в скрипте призрака.

Вопрос-ответ:

Ссылка на основную публикацию