Меню Рубрики

Как написать платформер на unity

Про создание платформера на Unity. Часть первая, характерная

Все мы здесь любим качественные пошаговые руководства для начинающих, чего уж греха таить. По платформерам на Unity руководств много, а вот качественных не то что бы и очень. Сегодня мы попробуем добавить в копилку хороших уроков еще один. А создавать мы будем персонажа для 2D-платформера, ни больше, ни меньше.

Присоединяйтесь, учитесь, но помните: под катом очень много гифок.

Итак, с чего начать создание персонажа? Конечно же, с его спрайта. Достаточно перетащить картинку из любой папки на жестком диске во вкладку Assets, а оттуда — прямо на сцену. Оговорюсь сразу, в этом уроке мы не будем рассматривать создание анимации. А вот в следующих частях цикла — будем.

Как видите, после добавления на сцену (условимся, что это полноценный аналог словосочетанию scene view) у спрайта появились два компонента. Первый — transform. Он отвечает за расположение любого игрового объекта на сцене, его масштаб и текущий угол поворота относительно осей. Компонент sprite renderer как раз занимается отрисовкой спрайта нашего обаятельного носача в процессе редактирования и игры.

Но пока персонаж всего лишь картинка, он не может взаимодействовать с окружающим его миром. Для этого на помощь приходят компоненты, спрятанные во вкладке physics2d. В нашем случае это box collider и circle collider. Первый мы добавим на верхнюю часть персонажа для столкновений со стенами и всем остальным, а второй расположим на уровне ног. Это позволит двигаться по наклонным поверхностям (и поверхностям с небольшим перепадом высот) без особых проблем.

Теперь, чтобы на героя действовала, допустим, гравитация, добавим ему rigidbody2D (ну или твердое тело, как вам больше нравится). Для этого все в том же меню add component -> physics2D выберем пункт rigidbody2D и к спрайту сразу же добавится еще один компонент.

Если вкратце:
mass отвечает понятно за что;
linear drag и angular drag — линейное и угловое сопротивление, соответственно;
gravity scale — коэффициент гравитации для конкретно этого объекта;
fixed angle отключает переворот персонажа при столкновении с чем-нибудь, допустим, летящим;
isKinematic фиксирует объект раз и навсегда в одной точке;
interpolate устанавливает режим сглаживания при отрисовке персонажа;

Для платформера стандартное значение гравитации (-9.81 по оси Y) не очень подходит, поэтому изменим его на какое-нибудь магическое число. Например, -30. Для этого зайдем в Edit — Project Settings — Physics2D и заменим нужное значение в инспекторе.

На этом пока перестанем добавлять персонажу компоненты. Но сделаем кое-что из него. Для того, чтобы нам не приходилось тысячу раз добавлять одинаковые компоненты на каждом, допустим, уровне, в Unity есть механика под названием prefabs. Она позволяет создать из игрового объекта «болванку», которую можно использовать много раз и менять как своей душе угодно, не боясь за то, что какие-то экземпляры могут не измениться. Для создания префаба достаточно просто перетащить объект из иерарахии во вкладку assets. В моем случае еще и в папку prefabs.

Как видите, оба экземпляра героя прекрасно создаются и существуют вместе. Теперь нужно создать платформу, на которой будет стоять наш большеносый друг. Перетащим спрайт на сцену и добавим ему polygon collider. Размеры этого коллайдера, к слову, можно менять, перетаскивая его вершины с зажатой кнопкой shift.

Самое время научить персонажа двигаться. Перетащим заранее подготовленный скрипт (его нужно скачать и сохранить в папку assets) прямо на персонажа в hierarchy view.

У этого кусочка кода есть ряд параметров, которые отвечают за поведение героя в игре.

maxSpeed и JumpForce — максимальная скорость (по горизонтали) и сила прыжка. Экспериментально проверено, что для массы, равной единице, и гравитации -30 значения maxSpeed=10 и jumpForce = 700 являются оптимальными.

groundCheck — дочерний объект, находящийся в нижней точке спрайта и отвечающий за определение того, находится ли нечто, чем мы управляем, на «земле»

whatIsGround — что, собственно, считать землей. В нашем случае «землей» считается все, кроме персонажа

groundRadius — некая величина, в пределах которой проверяется столкновение с поверхностью.

В итоге, строчка grounded = Physics2D.OverlapCircle (groundCheck.position, groundRadius, whatIsGround); проверяет, пересекает ли groundCheck с радиусом groundRadius поверхность и, допустим, запрещает прыгать в нужных случаях.

Давайте, наконец, запустим игру и посмотрим что же у нас сегодня получилось. Для этого нажмем кнопку Play в верхн… Да ладно, вы и сами это разглядели 🙂

Герой прекрасно двигается (хотя, возможно, и не совсем прекрасно), и это создает для нас отличные предпосылки продолжить создание платформера.

А в следующей части мы разберемся как управлять камерой, узнаем кому нужно зажигание звезд и создадим самого первого врага. И да, попутно исправим один критический баг, беспечно пропущенный в статью во время этого урока. Догадаетесь, какой?

Если эта статья вдруг пробудила в вас желание написать собственную игру, то не растрачивайте его впустую! Прямо сейчас проходит конкурс, стать участником которого слишком просто: достаточно зарегистрироваться, выложить свою игру в store и дождаться объявления результатов. А победителей ждут Xbox One и великолепные Lumia 930!

Пойду дописывать свой Angry Flappy Swompy 3 Deluxe. Stay tuned, вторая часть статьи в ближайшие дни!

А вот и другие наши статьи по схожей тематике:

Источник статьи: http://habr.com/ru/company/microsoft/blog/236125/

Туториал 4: 2Д платформер (для новичков). Часть 1.

Введение:

1. Шаг

Запустите Unity и создайте новый 2D-проект.

2. Шаг

3. Шаг

4. Шаг

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerMove : MonoBehaviour <

//переменная для скорости движения
public float speed;
//ссылочная переменная для компонента Rigidbody2D
Rigidbody2D rb;

void Start () <
//делаем ссылку на Rigidbody2D
rb = GetComponent Rigidbody2D > ();
>

void FixedUpdate () <
//декларация переменной с её инициализацией значением полученным с горизонтальной оси (значение лежит в области между -1 и 1)
float x = Input.GetAxis ( «Horizontal» );
//декларация локального вектора и инициализация посчитанным значением
//x: значение от InputManager * speed
//y: принять текущее значение, мы не будем его менять, из-за использования силы тяжести
//z: должно быть равно нулю, нам не нужно движение по оси Z
Vector3 move = new Vector3 (x * speed, rb.velocity.y, 0f );
//Изменить скорость игрока на вычисленный вектор
rb.velocity = move;
>
>

5. Step

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerMove : MonoBehaviour <

//в инспекторе мы можем выбрать, какие слои будут землёй
public LayerMask whatIsGround;
//позиция для проверки касания земли
public Transform groundCheck;
//переменная, которая будет true, если крыса находится на земле
public bool isGrounded;
//значение величины силы
public float jumpForce;
//переменная для скорости движения
public float speed;
//ссылочная переменная для компонента Rigidbody2D
Rigidbody2D rb;

void Start () <
//делаем ссылку на Rigidbody2D
rb = GetComponent Rigidbody2D > ();
>

//я буду использовать Update() для более точного определения прыжка
void Update () <
//проверка, нажат-ли прыжок и находится-ли крыса на земле
if ( Input .GetButtonDown ( «Jump» ) && isGrounded) <
//применяем силу на Rigidbody2D вдоль оси Y для прыжка
rb.AddForce ( Vector2 .up * jumpForce, ForceMode2D .Impulse);
//переключаем переменную, чтобы предотвратить следующий прыжок, или мы могли бы снова прыгнуть (до того, как isGrounded будет переключена в FixedUpdate ())
isGrounded = false;
>
>

void FixedUpdate () <
//изменяем переменную, зависящую от результата Physics2D.OverlapPoint
isGrounded = Physics2D .OverlapPoint (groundCheck.position, whatIsGround);
//декларация переменной с её инициализацией значением полученным с горизонтальной оси (значение лежит в области между -1 и 1)
float x = Input.GetAxis ( «Horizontal» );
//декларация локального вектора и инициализация посчитанным значением
//x: значение от InputManager * speed
//y: принять текущее значение, мы не будем его менять, из-за использования силы тяжести
//z: должно быть равно нулю, нам не нужно движение по оси Z
Vector3 move = new Vector3 (x * speed, rb.velocity.y, 0f );
//Изменить скорость игрока на вычисленный вектор
rb.velocity = move;
>
>

6. Step

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerMove : MonoBehaviour <

//в инспекторе мы можем выбрать, какие слои будут землёй
public LayerMask whatIsGround;
//позиция для проверки касания земли
public Transform groundCheck;
//переменная, которая будет true, если крыса находится на земле
public bool isGrounded;
//значение величины силы
public float jumpForce;
//переменная для скорости движения
public float speed;
//ссылочная переменная для компонента Rigidbody2D
Rigidbody2D rb;
//переменная контроля направления крысы
public bool isLookingLeft;

void Start () <
//делаем ссылку на Rigidbody2D
rb = GetComponent Rigidbody2D > ();
>

//я буду использовать Update() для более точного определения прыжка
void Update () <
//проверка, нажат-ли прыжок и находится-ли крыса на земле
if ( Input .GetButtonDown ( «Jump» ) && isGrounded) <
//применяем силу на Rigidbody2D вдоль оси Y для прыжка
rb.AddForce ( Vector2 .up * jumpForce, ForceMode2D .Impulse);
//sпереключаем переменную, чтобы предотвратить следующий прыжок, или мы могли бы снова прыгнуть (до того, как isGrounded будет переключена в FixedUpdate ())
isGrounded = false;
>
>

void FixedUpdate () <
//изменяем переменную, зависит от результата Physics2D.OverlapPoint
isGrounded = Physics2D .OverlapPoint (groundCheck.position, whatIsGround);
//декларация переменной с её инициализацией значением полученным с горизонтальной оси (значение лежит в области между -1 и 1)
float x = Input.GetAxis ( «Horizontal» );
//декларация локального вектора и инициализация посчитанным значением
//x: значение от InputManager * speed
//: принять текущее значение, мы не будем его менять, из-за использования силы тяжести
//z: должно быть равно нулю, нам не нужно движение по оси Z
Vector3 move = new Vector3 (x * speed, rb.velocity.y, 0f );
//изменить скорость игрока на вычисленный вектор
rb.velocity = move;
//проверка, совпадает ли направление взгляда с направлением движения
if (x 0 && !isLookingLeft)
//вызов функции поворота крысы, если проверка совпала
TurnTheRat ();
//проверка, совпадает ли направление взгляда с направлением движения
if (x > 0 && isLookingLeft)
//вызов функции поворота крысы, если проверка совпала
TurnTheRat ();
>

//функция поворота крысы
void TurnTheRat ()
<
//смена переменной показывающей направление взгляда на обратное значение
isLookingLeft = !isLookingLeft;
//поворот крысы через инвертацию размера по оси х
transform.localScale = new Vector3 (transform.localScale.x * -1 , transform.localScale.y, transform.localScale.z);
>

7. Step

8. Шаг

9. Шаг

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerAnim : MonoBehaviour <

//ссылочная переменная для аниматора
Animator anim;
//ссылочная переменная для rigidbody2D
Rigidbody2D rb;

void Start () <
//делаем ссылку на аниматор
anim = GetComponent Animator > ();
//делаем ссылку на Rigidbody2D
rb = GetComponent Rigidbody2D > ();
>

void Update () <
//меняем параметр speed в Animator. Используем значение скорости по оси х
anim.SetFloat ( «speed» , Mathf .Abs (rb.velocity.x));
>
>

10. Шаг

11. Шаг

12. Шаг

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerAnim : MonoBehaviour <

//ссылочная переменная для аниматора
Animator anim;
//ссылочная переменная для rigidbody2D
Rigidbody2D rb;
//ссылочная переменная для PlayerMove
PlayerMove pm;

void Start () <
//делаем ссылку на Animator
anim = GetComponent Animator > ();
//делаем ссылку на Rigidbody2D
rb = GetComponent Rigidbody2D > ();
//делаем ссылку на PlayerMove
pm = GetComponent PlayerMove > ();
>

void Update () <
//проверка, находится ли крыса на земле
if (pm.isGrounded) <
//меняем параметр isJumping на false
anim.SetBool ( «isJumping» , false );
//меняем параметр speed. Используем абсолютное значение вектора скорости по х
anim.SetFloat ( «speed» , Mathf .Abs (rb.velocity.x));
// если крыса не на земле
> else <
//меняем параметр speed на 0
anim.SetFloat ( «speed» , 0 );
//меняем параметр isJumping на true
anim.SetBool ( «isJumping» , true );
>
>

13. Step

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerSound : MonoBehaviour <

//ссылочная переменная для звукового файла
public AudioClip footsteps;

//публичная функция, получим доступ к ней из аниматора
public void FootStepsAudio () <
//воспроизвести заданный звук на позиции крысы
AudioSource .PlayClipAtPoint (footsteps, transform.position);
>
>

14. Шаг

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerSound : MonoBehaviour <

//ссылочная переменная для аудио-файла
public AudioClip footsteps;

//публичная функция, получим доступ к ней из аниматора
public void FootStepsAudio () <
//воспроизвести заданный звук на позиции крысы
AudioSource .PlayClipAtPoint (footsteps, transform.position);
>

//запустится если было касание другого Collider2D
void OnCollisionEnter2D ( Collision2D coll) <
//проверка тэга на тэг «Ground»
if (coll.gameObject.tag == «Ground» ) <
//воспроизвести заданный звук на позиции крысы
AudioSource .PlayClipAtPoint (footsteps, transform.position);
>
>

15. Шаг

Выберите Ground в иерархии. Создайте prefab Ground (перетащите объект в Assets). Поместите prefab Ground в сцену, как следующую платформу.

Выберите Main Camera и сделайте её дочерним объектом Rat (перетащите Main Camera на Rat). Камера будет следовать за крысой.

Можете изменить X-position камеры на 0, чтобы убрать рывки при повороте.
Я думаю, этого достаточно для первой части. Надеюсь, что вторая часть будет готова в мае-июне (у меня сейчас мало времени).

Источник статьи: http://xrayisgray.de/sites/tutorial_4_ru.html


0 0 голоса
Article Rating
Подписаться
Уведомить о
guest

0 Комментарий
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии