Учебные материалы для школы программирования. Часть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. Успехов!