Про створення платформера на unity

З минулої статті з цього циклу пройшло достатньо часу (а з попередніх їй статей - ще більше), тому саме час повернутися і розповісти вам як зробити саму підступну і злочинницьку частина будь-якої комп'ютерної гри - ворогів. Обмовлюся заздалегідь: тут ми не будемо розглядати створення штучного інтелекту для супротивників вашого персонажа. Подивимося на те, які типи супротивників найбільш поширені в платформер і як їх реалізувати за допомогою Unity.

Про створення платформера на unity

Обережно, під катом і раніше багато гифок!

Дисклеймер: весь показаний в статті код не є зразком для наслідування, прикладом ідеального коду та інших вигаданих і не існуючих в природі речей. Практики, застосовані в статті, можуть бути одними з безлічі рішень конкретної проблеми. А можуть і не бути.

Отже, поїхали. Я виділив чотири основних типи об'єктів, які можуть так чи інакше перешкодити героєві вашої гри досягти мети:

1) Статичні (обертові пилки, «смертельні» блоки ітд)

Про створення платформера на unity

2) ті, хто ходить по платформах (гриби і черепахи з Super Mario Bros)

Про створення платформера на unity

3) Літаючі (ворони з другого рівня Ghosts and Goblins)

Про створення платформера на unity

4) Стрілища (Баужя зі свого замку того ж Маріо)

Про створення платформера на unity

Ще є боси, але вони можуть об'єднувати в собі всі зазначені вище типи, тому на них зупинятися не будемо.

1) Статичні перешкоди.
Зробимо обертову пилку. Для реалізації такого «ворога» потрібні буквально пара речей - спрайт пили і скрипт, який буде її вирощують. Сказано зроблено.

Перетягуємо спрайт на сцену:

Створюємо новий скрипт (це, як правило, дуже просто)

І додаємо туди код, який виглядає приблизно так:


У публічній змінної speed задається швидкість обертання. Важливо отметітіть, що позитивне значення обертає пилу проти годинникової стрілки, а негативне - за годинниковою.

Тепер, щоб взаємодіяти з пилкою, додамо на неї який-небудь коллайдер (детально це описано в найцікавіших попередніх частинах) і змінимо тег об'єкта на який-небудь підходящий в даній ситуації.

Теги - хороша штука. Ми можемо призначити гравцеві тег player, ворогам тег enemy, а стін та підлоги - level. Після цієї нехитрої процедури перевірка того, з чим ми, наприклад, зіткнулися, буде відбуватися набагато простіше. А ще можна знайти який-небудь один (або все, що є на сцені) об'єкт з певним тегом. Робиться це приблизно так:

Масив всіх об'єктів із заданим тегом можна отримати використовуючи метод FindGameObjectsWithTag - простіше нікуди.

Повернемося до наших пил і створимо новий тег для ворогів в грі.

У скрипт персонажа додамо наступну перевірку


Як бачите, все елементарно: перевіряємо колізії, перевіряємо тег того, з чим зіткнулися. Якщо все погано, перезавантажуємо рівень. Або віднімаємо життя. Або що-небудь в цьому дусі. Ви ж грали в платформери, правда?

Ось як все це виглядає в результаті:

Ось так, просто і швидко, ми створили першого ворога - який, звичайно, не ворог, але цілком собі перешкоду. Йдемо далі.

2) ті, хто ходить, що плазують і інші вороги, що переміщаються по платформах.
Непідготовленому читачеві може здатися що цей тип ворогів складніше в реалізації ніж перший. Поспішаю заспокоїти - це зовсім не так. Як і в попередньому випадку, нам потрібні який-небудь спрайт, коллайдер на ньому, скрипт і платформа, по якій все це буде рухатися. До цього невеликого списку додасться лише rigidbody2D, щоб на ворога діяла фізика і можна було встановлювати йому швидкість.

На жаль, малювати я не вмію і мого творчого таланту вистачило тільки на такого лиходія:

Про створення платформера на unity

Для його переміщення використовуємо наступний скрипт

Задаємо швидкість ворога і напрямок його руху (-1 - вліво, 1 - вправо), яке можна змінювати при зіткненні зі стінами, наприклад. Далі просто - встановлюємо горизонтальну швидкість, що дорівнює добутку значення швидкості і напряму.

Кумедний факт - якщо поставити у rigidbody2D галку fixedAngle, то ворог буде повзти, а якщо прибрати, то


«Але він дивиться вправо, а рухається вліво!» - помітить уважний читач. Давайте пофиксил це і будемо розгортати спрайт відповідно напрямку руху:


І навчимо розгортатися при зіткненні зі стіною. Для цього зробимо на рівні пару стін з тегом wall і напишемо обробку колізій. Ось таку:


Тепер, коли все на місці, підсумковий результат буде виглядати ось так.

Залишиться тільки додати ворогові тег Enemy для того, щоб він дійсно став небезпечний для нашого персонажа.

Підіб'ємо проміжний підсумок. Ми розібрали як створюються два типи «ворогів» в 2D-платформер: статичні і переміщаються по рівню. Як бачите, це дійсно дуже просто і базова реалізація займає зовсім мало часу.

У наступній частині я розповім як створити два інших виду ворогів - літаючих і стріляючих.
Stay tuned - буде цікаво!

Ще трохи корисних посилань

Ні в якому разі не можна обертати або переміщати колайдери без твердих тіл. Це викликає їх пересозданіе і повний перерахунок всієї фізики в кадрі. Також, не можна переміщати тверді тіла через їх трансформи. Ви можете цього не помітити на одній пилі, але вже пару сотень поставлять будь-який мобільний пристрій на коліна. Додайте на пилку kinematic тверде тіло, вимкніть йому гравітацію і виправте скрипт:

Єдиний допустимий варіант обертання об'єкта з колайдером


Без профайлера причина майбутніх гальм буде зовсім неочевидна. Тест на 240 пилах. Зліва - ваша реалізація. Посередині - пила з твердим тілом, але обертання через трансформ. Праворуч - моя реалізація.

Багаторазова різниця в продуктивності

В даному конкретному випадку є ще більш швидка альтернатива - робите статичний об'єкт пили, з колайдером, але без спрайту, додаєте йому в дітей ще один об'єкт, але з спрайтом і обертає саме його. Але можна забути, що тіло не можна рухати, додати якісь рухомі обертаються пили і напоротися на ту ж помилку ...

(Прошу вибачення, що змушую ванговать, шматки початкових кодів зможу відправити тільки ввечері)

Я так розумію, і планети, і об'єкти у вас - тверді тіла, а не просто колайдери. Тверде тіло не може бути дитиною твердого тіла і при цьому вести себе нормально - батько буде «домінувати» непередбачуваним чином, тому у вас не працювало успадкування.
MovePosition і MoveRotation виконують, по суті, фізичну телепортацію за один кадр, що може бути застосовано лише в дуже простих або дуже синтетичних випадках, на зразок обертання пилки або руху рівня навколо гравця. Тобто якщо ваші тверді тіла кінематичні і слідують спрощеними правилами симуляції. Швидкість, сила, тертя - більш складні поняття і при телепортації можуть ламатися. Якщо ви плануєте використовувати MovePosition з MoveRotation і вам хочеться мати сили і швидкості - вам доведеться написати з їх використанням свій власний addForce, addVelocity і.т.п. тому що наявні можуть вести себе непередбачувано криво.
Якщо вам потрібно просто почати красиво падати на планету при прольоті мимо - додавайте силу в напрямку її центру в OnTriggerStay2D - це буде найкращим рішенням. Якщо вам потрібно вийти на орбіту і триматися на ній, при цьому використовуючи фізичний движок ... все буде набагато складніше, доведеться дістати шкільних підручників з фізики і це вже тема для окремої статті.
Думаю, на тижні напишу статтю про свою боротьбу з фізикою в Unity ... в нашій грі фізика використовується ну дуже специфічно і движок був явно не готовий до таких конструкцій.

Схожі статті