Статьи

Работа с физикой Unity3D

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

Какой современный игровой движок будет полным без физического движка? Каждый текущий игровой движок, будь то 3D или 2D, имеет какую-то физическую библиотеку, и Unity не является исключением. Физика в реальном времени идеально подходит для моделирования сложных взаимодействий между объектами в вашей игре. Физический движок может сэкономить много ручного кодирования и анимации для достижения реалистичного движения, может упростить выполнение обнаружения ударов и быстро внедрить множество новых игровых механизмов в ваши игры.

В этом уроке мы будем использовать физический движок в Unity для создания трехмерной игры, похожей на BoomBlox и Angry Birds. Мы научимся придавать объектам разные физические свойства, делать их способными к столкновению и даже позволять им разрушаться, если столкновения достаточно сильны.

Финальная игра

Физический движок работает, моделируя, как объекты реагируют друг с другом, когда к ним применяются силы. Эти силы могут быть постоянными, как сила тяжести или импульс транспортного средства, в то время как другие являются короткими и мощными, как взрывы. Физическое моделирование иногда называют «песочницей», потому что это влияет только на объекты в моделировании. Действительно, не каждый объект в вашей игре должен быть частью симуляции. Это важно, так как движения игрока часто должны быть нереалистичными, в то же время реалистично реагируя на столкновения.


  • Нажмите Файл> Новый проект
  • Перейдите в подходящую папку и назовите проект CannonBowl
  • Нажмите Создать
  • Нажмите GameObject> Создать другой> Направленный свет
  • Нажмите Файл> Сохранить сцену
  • Назовите сцену Главная
  • Нажмите Сохранить

Коллайдеры — это то, что физические движки используют для обнаружения попаданий. В отличие от объектов сетки, они знают, когда они вступили в контакт друг с другом. Это простые формы, такие как коробки, сферы или капсулы, которые назначаются вашим GameObjects и следуют за ними. Вы можете думать о них как о чем-то вроде «силового поля».

Удобно, когда бы ни создавался GameObject, ему автоматически назначается соответствующий коллайдер. Куб получает BoxCollider, Сфера получает SphereCollider, Цилиндр получает CapsuleCollider и так далее.

Коллайдеры

В конечном итоге нам понадобится несколько блоков, чтобы сбить:

  • Нажмите GameObject> Создать другое> Куб
  • Переименовать куб в WoodBlock
  • Установите позицию блока в 0, 0, 0. Это будет центрировать блок в мире
  • Скачать Wood.jpg
  • Перетащите Wood.jpg на панель Project, чтобы сделать его текстурой.
  • Перетащите текстуру дерева на блок в окне сцены, это автоматически создаст для нас материал дерева и примените его к блоку.
  • Перетащите блок с панели «Иерархия» на панель «Проект», чтобы превратить его в сборный.

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


Твердое тело — самый важный элемент физического движка. Любой GameObject, к которому он прикреплен, включается в симуляцию.

  • Выберите блок «Заблокировать» на панели «Проект».
  • Нажмите Компонент> Физика> Жесткое тело
Компонент твердого тела

По умолчанию на твёрдое тело влияют сила тяжести и сопротивление воздуха, также известное как сопротивление. Если мы нажмем Play, блок начнет падать, ускоряться и в конечном итоге достигать конечной скорости, когда сила тяжести и сопротивление уравниваются.


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

  • Нажмите GameObject> Создать другое> Плоскость
  • Переименовать самолет в землю
  • Установите позицию Земли на 0, 0, 0
  • Скачать Grass.jpg
  • Перетащите Grass.jpg на панель «Проект», чтобы сделать ее текстурой.
  • Перетащите текстуру травы на землю в режиме просмотра сцены

Земля автоматически получит MeshCollider, который будет препятствовать прохождению любых твердых тел через нее. Нажмите Play, и блок должен упасть и осесть на землю.

Сила тяжести

Теперь нам нужна структура, чтобы сбить с ног. Выберите блок и нажмите Ctrl + D в Windows или Cmd + D в OSX, чтобы дублировать блок несколько раз. Используйте инструменты масштабирования и перемещения, чтобы растянуть и расположить блоки примерно в той же конфигурации, что и на рисунке ниже.

Структура

ПРИМЕЧАНИЕ. Рекомендуется использовать точные числа для ваших преобразований. Блоки должны опираться друг на друга, но не перекрываться. Перекрытия приведут к тому, что физический движок выйдет из строя и сделает непредсказуемые вещи.


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

  • Нажмите Активы> Создать> C # Script
  • Переименуйте сценарий в Cannon (потому что в конечном итоге наша камера будет снимать)
  • Перетащите сценарий на основную камеру
  • Дважды щелкните скрипт, чтобы отредактировать его

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

01
02
03
04
05
06
07
08
09
10
11
12
13
public class Cannon : MonoBehaviour {
    void LateUpdate() {
        float x = Input.GetAxis(«Mouse X») * 2;
        float y = -Input.GetAxis(«Mouse Y»);
 
        // vertical tilting
        float yClamped = transform.eulerAngles.x + y;
        transform.rotation = Quaternion.Euler(yClamped, transform.eulerAngles.y, transform.eulerAngles.z);
 
        // horizontal orbiting
        transform.RotateAround(new Vector3(0, 3, 0), Vector3.up, x);
    }
}

В качестве последнего штриха давайте упростим прицеливание, добавив в нашу камеру перекрестие:

  • Нажмите GameObjects> Создать> Плоскость
  • Переименовать самолет в перекрестие
  • Установите положение перекрестия на 0, 0, 0
  • Скачать Crosshair.png
  • Перетащите Crosshair.png на панель «Проект».
  • Перетащите текстуру перекрестия на плоскость перекрестия на панели «Сцена».
  • В инспекторе щелкните правой кнопкой мыши компонент MeshCollider и удалите его, чтобы он не влиял на другие физические объекты в сцене.
Камера с перекрестием

Умение смотреть на нашу структуру — это нормально, но это должно быть о физике! Нам нужен способ разобраться с этим, чтобы увидеть физику в действии. Нам нужно что-то снимать!

  • Нажмите GameObject> Создать другое> Сфера
  • Переименовать сферу в пушечное ядро
  • Установите положение пушечного ядра на 0, 0, 0
  • Выбрав пушечное ядро, выберите Компоненты> Физика> Твердое тело
  • Перетащите «Пушечное ядро» с панели «Иерархия» на панель «Проект», чтобы превратить его в сборный.

Так как мы собираемся снимать пушечные ядра прямо с камеры, мы можем редактировать наш существующий сценарий Cannon. Сначала мы добавляем открытый атрибут в верхней части класса для нашего префаба с снарядом.

1
2
public class Cannon : MonoBehaviour {
    public GameObject projectilePrefab;

Мы добавляем метод FixedUpdate, чтобы прослушивать нажатие кнопки «Fire1», а затем создаем экземпляр префаба «Пушечное ядро», помещаем его в камеру и затем добавляем к нему силу, чтобы продвигать ее вперед.

1
2
3
4
5
6
void FixedUpdate () {
    if (Input.GetButtonDown(«Fire1»)) {
        GameObject projectile = Instantiate(projectilePrefab, transform.position, transform.rotation) as GameObject;
        projectile.rigidbody.AddRelativeForce(new Vector3(0, 0, 2000));
    }
}

Возможно, вы заметили, что если пушечное ядро ​​выстреливает достаточно далеко, оно может упасть с края нашей наземной плоскости. Это пушечное ядро ​​будет существовать до тех пор, пока игра будет продолжаться, а ее физика будет продолжать рассчитываться, что в конечном итоге замедлит ход событий. Нам нужно создать границу вокруг уровня и уничтожить любые игровые объекты, которые покидают эту границу.

  • Нажмите GameObject> Создать пустой
  • Переименуйте его в Границу
  • Установите границы, x, y и z на 0
  • Выделив Границу, выберите Компоненты> Физика> Box Collider
  • В инспекторе убедитесь, что флажок Is Trigger отмечен
  • Установите Box Collider’s Center на 0, 25, 0
  • Установите размер ящика коллайдера на 50, 50, 50
граничный

Теперь нам нужно создать скрипт, который будет уничтожать и объекты, которые уходят за границы.

  • Нажмите Активы> Создать> C # Script
  • Переименуйте скрипт в Границу
  • Перетащите сценарий на объект «Граница» на панели «Иерархия».
  • Отредактируйте скрипт и добавьте следующий код
1
2
3
4
5
public class Boundary : MonoBehaviour {
    void OnTriggerExit(Collider other) {
        Destroy(other.gameObject);
    }
}

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

  • Нажмите Активы> Создать> C # Script
  • Переименуйте скрипт в Block
  • Перетащите сценарий на сборный блок на панели «Проект».
  • Дважды щелкните скрипт на панели «Проект», чтобы отредактировать его.

В сценарии мы даем сборному свойству public свойство Health, которое можно настроить в редакторе. Это позволяет различным блокам иметь разное количество здоровья.

1
2
public class Block : MonoBehaviour {
    public float health = 20;

При обнаружении столкновения измеряется величина удара. Чем больше величина, тем больше был нанесен ущерб. Все, что выше легкого крана, вычитается из здоровья блока. Если здоровье блока падает ниже 0, блок разрушается сам. Затем он проверяет, сколько других блоков осталось на сцене. Если остался только один блок, игра заканчивается, и она перезагружает сцену, чтобы играть снова.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
void OnCollisionEnter(Collision collision) {
    // apply collision damage
    if (collision.relativeVelocity.magnitude > 0.5) {
        health -= collision.relativeVelocity.magnitude;
    }
 
    // destroy if health is too low
    if (health <= 0) {
        Destroy(gameObject);
 
        // restart the scene if this was the last box
        GameObject[] boxes = GameObject.FindGameObjectsWithTag(«Box»);
        if (boxes.Length <= 1) {
            Application.LoadLevel(«Main»);
        }
    }
}

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

  • На панели «Проект» продублируйте префаб WoodBlock ( Ctrl + D в Windows, Cmd + D в OSX).
  • Переименуйте дубликат в ConcreteBlock
  • Скачать Concrete.jpg
  • Перетащите Concrete.jpg на панель «Проект».
  • Перетащите текстуру «Бетон» на сборный бетонный блок на панели «Проект».
  • С выбранным префабом используйте Инспектора, чтобы обновить Здоровье до 50
  • В компоненте Rigidbody увеличьте массу до 5, чтобы сделать ее тяжелее
  • Перетащите сборный бетонный блок в сцену

Попробуйте заменить некоторые поперечины на бетонные блоки. Бетонные блоки должны быть труднее опрокинуть, упасть с большим ударом, и их будет сложнее уничтожить пушечными ядрами.

Бетонные блоки

Ниже приведена законченная игра, запущенная в Unity Web Player. Используйте мышь, чтобы вращаться вокруг камеры, и нажмите Ctrl или левую кнопку мыши, чтобы стрелять пушечными ядрами.

Unity Web Player. Install now!

Этот урок только поверхностно показывает, на что способен физический движок Unity. Постоянные силы, взрывные силы, физические материалы, шарниры, пружины, тряпичные куклы и т. Д. Несмотря на то, что это может показаться пугающим, все элементы физического движка Unity сочетаются друг с другом, облегчая понимание и реализацию физики в ваших играх.

Чтобы узнать больше о возможностях физического движка Unity, посетите:

http://docs.unity3d.com/Documentation/Manual/Physics.html