Игровые механики на уроке геометрии или векторы на Unity 3D

от автора

Учебные материалы для школы программирования. Часть 16

Предыдущие уроки можно найти здесь:

В этой статье, мы обратим свой взор в прошлое, и вспомним, с чего начиналась детская школа программирования Step to Science. Первоначальная идея проекта состояла в том, чтобы быть не просто кружком технического творчества, а стать для детей ответом на вопрос, «зачем учиться в школе?»

К чему нам физика, алгебра и геометрия, если мы не планируем проектировать космические корабли, если для счета у нас есть калькулятор в телефоне, расплачиваемся мы чаще картой, так что даже сдачу в уме считать не надо.
Я тоже в детстве вела такие рассуждения, и у родителей не было иных способов донести до меня истину, кроме фразы «нет слова не хочу, есть слово надо» и ремня, который без лишней полемики мотивировал садиться за уроки.

С возрастом, перейдя на другую сторону баррикад, я поняла что хочу ребятам объяснить, показать, доказать, что учиться в школе действительно важно! И игровой проект, который мы разберем сегодня — один из цикла занятий по изучению школьных предметов через игры на Unity 3D.

Кроссплатформенный движок Unity дает огромные возможности учителю: через увлекательный процесс создания игр мы изучаем законы физики, геометрии, делаем расчеты, проектируем окружение, используем сторителлинг, сценарные механики. И конечно-же программируем. Вариантов интеграций Unity в другие образовательные и предметные области — бесчисленное множество!

Порядок выполнения

На примере создания 2D игры «баскетбол», рассмотрим векторы (скорости, сил, локальной и глобальной систем координат). Разберем принципы представления систем координат и представления векторов. Также будет затронута работа с LineRenderer и многокамерность.

Поехали!

Создадим новый проект и импортируем в него приложенный ассет.
Ассет содержит в себе все ресурсы, необходимые для создания полноценного 2D приложения.

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

Конечно, необходимо выставить правильный Order in layer у спрайтов. Добавим мяч, применим к нему Circle collider и Rigidbody.

Внутри мяча должен находиться пустой объект с Audio Source, настроенным на воспроизведение звука удара.

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

using System.Collections; using System.Collections.Generic; using UnityEngine;  public class Ball : MonoBehaviour {     public AudioSource hitSound;     public Rigidbody2D rig;      // Use this for initialization     void Start () {      }      // Update is called once per frame     void FixedUpdate() {      }      private void OnCollisionEnter2D(Collision2D other) {         if (other.relativeVelocity.magnitude > 1f) {             hitSound.Play();             hitSound.volume = Mathf.Clamp01(other.relativeVelocity.magnitude / 10);             rig.velocity *= 0.8f;         }     } }

В скрипте нет автопоиска Rigidbody, так что придётся закинуть его руками. Если нажать на Play, наш мяч упадёт, издавая звуки. Чтобы мяч отскакивал, создадим физический материал и закинем его на коллайдер мяча.

Теперь подумаем о том, чтобы мяч показывал своё направление. Для этого создадим скрипт, который рисует стрелки: нам понадобятся два пустых объекта с LineRenderer, один в другом.

Создадим материал для стрелки:

И добавим скрипт, который будет выставлять вершины LineRenderer’ов, делая из них стрелки:

using System.Collections; using System.Collections.Generic; using UnityEngine;  public class Arrow : MonoBehaviour {    public Vector3 showVector;     public LineRenderer lrenderer1;     public LineRenderer lrenderer2;     Transform myTransform;      // Use this for initialization     void Start () {         //lrenderer1 = GetComponent<LineRenderer>();         myTransform = transform;     }     // Update is called once per frame     void Update () {         showVector = new Vector3(showVector.x, showVector.y, 0f);          lrenderer1.SetPosition(0, myTransform.position);         lrenderer1.SetPosition(1, myTransform.position + showVector);            if (showVector.magnitude >= 2f) { // длинная стрелка             lrenderer2.SetPosition(0, myTransform.position + showVector - showVector.normalized);         } else {             lrenderer2.SetPosition(0, myTransform.position + showVector * 0.5f);         }         lrenderer2.SetPosition(1, myTransform.position + showVector);          if (showVector.magnitude < 0.1f) {             lrenderer1.enabled = lrenderer2.enabled = false;         } else {             lrenderer1.enabled = lrenderer2.enabled = true;         }     } }

Закинем скрипт на объект-родитель стрелки и настроим его.

Теперь надо написать скрипт, который будет вектор скорости передавать в наш скрипт «показывания» стрелки. Он очень простой:

using System.Collections; using System.Collections.Generic; using UnityEngine;  public class VectorVelocity : MonoBehaviour {     public Rigidbody2D rig;     public Arrow arrow;      // Use this for initialization     void Start () {       }      // Update is called once per frame     void Update () {         if (rig.bodyType == RigidbodyType2D.Dynamic) {             arrow.showVector =  rig.velocity / 5f;         }     } }

Закинем его на мяч, в скрипте укажем риджибади мяча и объект со скриптом стрелки.

Теперь вектор скорости показывается верно. Вектор скорости уменьшен в 15 раз, чтобы его было хорошо видно. А для того, чтобы было видно траекторию мяча — добавим ему Trail Renderer на любой привязанный к мячу объект.

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

Листинг скрипта:

using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems;  public class Spawner : MonoBehaviour {      public Rigidbody2D ball;     public TrailRenderer tr;      Quaternion oldRotation;     Vector3 oldPosition;      public bool readyToShoot = true;      // Use this for initialization     void Start () {         oldPosition = ball.transform.position;         oldRotation = ball.transform.rotation;     }      // Update is called once per frame     public void Respawn () {         ball.transform.position = oldPosition;         ball.transform.rotation = oldRotation;          ball.velocity = Vector3.zero;         ball.angularVelocity = 0;         ball.bodyType = RigidbodyType2D.Kinematic;          readyToShoot = true;         tr.Clear();     }      public void Shoot(Vector3 speed) {         if (!readyToShoot) {             return;         }          ball.bodyType = RigidbodyType2D.Dynamic;         ball.velocity = speed;         readyToShoot = false;     } }

Скрипт выкладываем на пустой объект в мире и устанавливаем ему наш мяч в качестве риджитбади и его трейл.

Этот скрипт сам по себе ничего не делает. Чтобы он работал, необходимо организовать ввод. Создадим UI -> Panel на сцене, выставим панели нулевую альфу и установим на него скрипт TouchPanel.cs , приложенный в проект.

Внутри панели должен лежать спрайт со следующими параметрами (обратите внимание на привязку):

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

Для того, чтобы сделать включение/выключение стрелок, используется скрипт Toggle, который реализован через эвент-систему юнити. Его необходимо закинуть на кнопку и сконфигурировать следующим образом.

Готово!

P.S. Делитесь ссылкой на статью с коллегами, друзьями и любопытными учениками. Будет здорово, если вы попробуете провести один из уроков в своей школе или в кружке детского технического творчества, и напишите пару слов обратной связи о том, как прошел урок по Unity 3D. Успехов!

ссылка на оригинал статьи https://habr.com/ru/post/553420/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *