Создание шутера на Unity3D
3D шутер c мультиплеером в Unity / Урок #1 — Начало
Приступаем к видеокурсу по созданию шутера на Unity. Это будет полноценная 3D игра с возможностью мультиплеера. За курс мы узнаем как сделать шутер в Unity (Unity3D) с возможностью игры по серверу.
Видеоурок
Полезные ссылки:
- Официальный сайт Unity ;
Информация про Unity
Unity – это игровой движок, на котором строится большая часть современных игр на разных платформах. Посредством движка реально создавать игры, ориентированные на запуск на компьютерах (Windows, Linux, MacOS), мобильных телефонах, планшетных компьютерах (Android, iOS, Windows Phone) и даже игровых приставках PlayStation, Xbox, Nintendo.
Создание игр на движке Unity невозможно представить без написания дополнительного кода. В Unity поддерживается два языка программирования — JavaScript и C# . Раньше также поддерживался язык Boo, но позже от него отказались.
Вы можете самостоятельно выбрать на каком языке программировать в Unity, так как особого значения это не имеет. Большинство разработчиков дают предпочтение языку C# , так как он более мощный и найти различную документацию намного проще, нежели для языка JavaScript .
В Unity используется встроенные функции, которых нет ни в C#, ни в JavaScript. За счёт этого особо не имеет значения знает вы язык программирования или нет. Тем не менее, мы все же рекомендуем сперва пройти курс по изучению языка C#. Курс представлен на нашем сайте по этой ссылке .
Как сделать шутер на Unity?
Разработка игр на Unity ведется в два этапа:
- построения дизайна через Unity графический дизайнер;
- написание скриптов через язык C#.
Мы за курс будем делать стрелялку на Unity с возможностью игры по сети. Для создания своей игры стрелялки необходимо продумать дизайн основных игроков, добавить к ним оружие и продумать систему выстрелов на основе RayCast.
Шутер на Юнити создается столь же просто, как и другие проекты.
План курса
Наша игра не будет иметь потрясающего сюжета или же красивого дизайна, так как нашей задачей является создание всей механики и настройка мультиплеера в игре. Мы построим небольшую карту с игроками, добавим механику передвижения, механику стрельбы и проработаем все классы для создания шутера в Unity3d .
Для реализации мультиплеера мы будем использовать возможности серверов от Unity. Unity предоставляет бесплатный и очень удобный функционал, который можно использовать для подобных целей.
В ходе курса вы не только научитесь создавать шутер с мультиплеером, но также улучшите свои знания и навыки в создании игр на движке Unity.
Создаём простой зомби-шутер на Unity
Преподаватель курса по геймдеву Николай Запольнов пошагово описывает процесс создания простейшего шутера на Unity. Статья подойдёт новичкам.
В преддверии старта нового потока курса «Unity Game Developer. Professional», подготовили статью по мотивам урока от преподавателя курса — Николая Запольнова, где он пошагово разъяснил процесс создания простейшего шутера на Unity.
Статья нацелена в первую очередь на новичков с базовыми знаниями терминологии программирования. Главной её целью является желание показать, что при некотором багаже знаний вы сможете довольно скоро освоить работу с движком и создадите свои первые проекты.
Последующие разделы могут показаться простыми и не дадут ничего нового, если вы уже опытный специалист в разработке игр на Unity.
Введение в Unity
Можете пропустить раздел, если вы уже знакомы с этим редактором. Переходите к разделу «Игровой мир: начало».
Базовым блоком при создании шутера на Unity является «сцена», представляет, обычно, 1 уровень игры. Однако, бывает так, что одна сцена включает несколько уровней, или один объёмный уровень дробится на ряд сцен. Сцена, как матрёшка, состоит из объектов, наполненных компонентами.
Именно компоненты делают интерфейс живым и привлекательным, обеспечивают такие функции как, например, визуализация, анимация, реалистичность. С помощью C# разработчик может сам написать их, сформировать нужную ему логику будущей игры. Перейдём непосредственно к движку.
После запуска редактора и создания нового файла, перед вами появится окно, состоящее из 4-х основных областей:
Слева вверху расположено окно Hierarchy, в котором отображается иерархия игровых объектов сцены: камеру (Main Camera), отображающую виртуальный мир глазами играющего, и источник света (Directional Light), определяющий направление освещённости сцены, без которого она выглядела бы как чёрное поле.
По центру расположено окно Scene, где, собственно, можно визуально редактировать уровень — вращать и передвигать с помощью мыши, получая наглядный результат. Справа от него находится вкладка Game (на скриншоте она неактивна). При переключении на неё кнопкой со значком воспроизведения сцена отображается через Main Camera.
В правой части экрана можно увидеть фрэйм Inspector — представляет собой набор полей с параметрами отмеченного объекта с возможностью их редактирования. На картинке видны 2 компонента: Transform, отвечающий за положение камеры, и, непосредственно, Camera — воплощает её функционал. Компонент Transform свойственен всем игровым объектам в Unity.
Внизу окна находится вкладка Project, содержащая цифровые объекты проекта (ассеты). По сути, это файл с данными, которые можно применить для создания сцен и интерфейса: текстуры, двумерные и трёхмерные элементы, звуковое сопровождение, анимация и конфигурации. Разработчики, не обладающие выдающимися навыками графического дизайна, могут загружать ассеты из Unity Asset Store в том числе и бесплатно. Также в Unity поддерживается опция загрузки файлов в стандартных форматах, например, png, jpg, fbx.
Справа от Project можете наблюдать неактивную вкладку Console. Здесь отображаются баги (ошибки), которые стоит периодически отслеживать, и сюда можно вводить части кода с целью отладки.
Игровой мир: начало
Неумение рисовать для разработчика игр — не приговор. В представленном примере взята графика из бесплатного раздела Unity Asset Store (ссылки внизу статьи), с помощью которой был собран элементарный уровень:
Выбранные элементы можно просто перетащить в окно проекта при помощи мыши и расположить по желанию:
Помимо этого, в Unity можно в один клик наполнять сцену типовыми объектами: сфера, куб, плоскость. Это делается нажатием правой кнопки мыши в области Hierarchy, из предложенного списка можно выбрать нужный элемент. В качестве примера — 3DObject⇨Plane. В представленной сцене из этих плоскостей с наложением текстуры собран асфальт. Текстура выбрана также в Unity Asset Store.
Важно!
Наземное покрытие состоит именно из нескольких областей, а не из одной с высоким значением scale, поскольку при такой схеме покрытие выглядит более естественно, без чрезмерного увеличения текстуры. Можно, конечно, поиграть с параметрами материала, но представленный вариант является более простым и подходит для новичков.
И всё-таки оно движется!
Игровой мир уже вырисовывается, но на уровне пока отсутствует динамика. Согласно концепции, игрок будет противостоять атакам зомби, для этого они должны не только «видеть» персонажа игрока, двигаться в его сторону, но и огибать преграды на пути.
Для реализации этих функций используется инструмент «навигационная сетка» (Navigation Mesh). По конфигурации уровня он вычисляет пространства, где можно двигаться, группирует их и даёт возможность поиска оптимального расстояния между двумя точками сцены. Информация сохраняется в ассет с возможностью последующего редактирования, это называется «запекание» (baking). Для более сложных сцен с динамичными преградами используется компонент NavMeshObstacle.
Обратите внимание, чтобы Unity мог распознать объекты верно, следует в области “Inspector” напротив объектов отметить Navigation Static и кликнуть стрелку вниз для параметра Static:
И хоть пока мы не будем обращаться к остальным опциям в данной области, они также важны в процессе качественной визуализации сцены. Вам будет полезно с ними разораться позже, поскольку даже одна галочка может серьёзно улучшить внешний вид.
В меню нужно выбрать Window⇨AI⇨Navigation⇨Bake. В открывшейся вкладке Unity попросить обозначить физические параметры объектов: радиус персонажа, высоту ступеней и так далее. Оставляем предустановленные значения, нажимаем кнопку Bake.
После проведения нужных расчётов Unity выдаст результат:
Область для передвижений обозначается синим цветом. Вокруг препятствий автоматически устанавливается небольшое дополнительное расстояние, которое зависит от радиуса героя. Благодаря этому персонаж не будет застревать в текстурах.
При наличии навигационной сетки можно использовать NavMeshAgent для поиска и управления траекторией перемещения игровых объектов в сцене.
Перейдём к персонажу зомби. Для его создания нужно добавить объёмную модель из ассетов и компонент NavMeshAgent:
На языке C# разработаем компонент, чтобы персонаж начал движение, а NavMeshAgent знал направление.
В Unity нужно выбрать корневую папку Assets, где нажатием правой кнопки мыши будет создана папка Scripts. Именно в ней будут находится все скрипты для облегчения поиска. В созданной папке создаём файл C# с именем Zombie и добавим в соответствующий игровой объект:
Скрипт открывается двойным щелчком левой кнопки мыши. Далее представлен результат в Unity:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Zombie : MonoBehaviour < // Start is called before the first frame update void Start() < >// Update is called once per frame void Update() < >>
Unity подключил библиотеки для типовой заготовки System.Collections и System.Collections.Generic, которые часто необходимы в коде игр, а также UnityEngine с интерфейсом прикладного программирования движка.
Автоматически был создан класс под названием Zombie, которое совпадает с именем файла. Это важно, поскольку так Unity соотносит компонент и относящийся к нему скрипт.
Класс является производным от MonoBehaviour (базового класса для пользовательских компонентов). Он содержит 2 метода, которые будут вызываться автоматически: Start — после загрузки сцены, Update — покадрово. Это одни из множества аналогичных функций, которые вызывает движок. С полным перечнем можно ознакомиться здесь: https://docs.unity3d.com/Manual/ExecutionOrder.html.
Пришло время заставить зомби перемещаться по карте. Следует в начало файла вставить директиву using UnityEngine.AI, чтобы подключить библиотеку UnityEngine.AI, где хранятся NavMeshAgent и иные классы, относящиеся к сетке. Для этого добавим в начало файла директиву using UnityEngine.AI.
Доступ к нужному классу можно получить, применив метод GetComponent (метод вызывается из компонента и возвращает значение в виде ссылки на любой другой компонент того же объекта). Создадим в классе поле NavMeshAgent navMeshAgent, с помощью Start получим ссылку на NavMeshAgent, и зададим движение в точку с координатами (0;0;0). Итоговый код должен иметь вид:
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.AI; public class Zombie : MonoBehaviour < NavMeshAgent navMeshAgent; // Start is called before the first frame update void Start() < navMeshAgent = GetComponent(); navMeshAgent.SetDestination(Vector3.zero); > // Update is called once per frame void Update() < >>
После запуска игры зомби двинется в центр сцены:
На данный момент этот блок не поддерживается, но мы не забыли о нём! Наша команда уже занята его разработкой, он будет доступен в ближайшее время.
Уровень стал динамичнее, но не хватает противостояния. Нужно добавить игрока, который самоотверженно будет сражаться с мертвяками.
Игровой объект Player создаётся так же, как и для зомби — на основе 3D-модели. Выберем теперь полицейского, дополним компонентом NavMeshAgent и скриптом с соответствующим названием.
Файл с кодом Player пока остаётся без изменений, при этом потребуется внести исправления в скрипт Zombie. Игрока лучше наделить более высоким приоритетом, указав для свойства Priority в компоненте NavMeshAgent число меньше 50. Таким образом, при встрече на карте игрок будет иметь более крепкую позицию и сможет оттолкнуть зомби.
Чтобы преследовать игрока, зомби нужно видеть его местоположение. С помощью стандартного метода FindObjectOfType необходимо получить ссылку на игрока в классе Zombie. После этого обратимся к компоненту transform игрока с запросом значения position. Чтобы шутер был захватывающим, важно, чтобы зомби нападали в течение всей игры, а не только в начале, поэтому надо задать цель для NavMeshAgent в Update. Скрипт выглядит так:
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.AI; public class Zombie : MonoBehaviour < NavMeshAgent navMeshAgent; Player player; // Start is called before the first frame update void Start() < navMeshAgent = GetComponent(); player = FindObjectOfType(); > // Update is called once per frame void Update() < navMeshAgent.SetDestination(player.transform.position); >>
Проверяем, находит ли зомби цель для нападения:
На данный момент этот блок не поддерживается, но мы не забыли о нём! Наша команда уже занята его разработкой, он будет доступен в ближайшее время.
Итак, всё готово для зомби-апокалипсиса. Но пока главный герой неподвижен, у него нет шансов на спасение, поэтому надо научить его уворачиваться от атаки.
Игрок управляется с помощью определённых комбинаций нажатия клавиш, значения которых в Unity возвращает метод GetKey, входящий в стандартный класс Input.
Важно!
Такое решение задачи принято для упрощения кода. Однако, общепринятым считается использование Input.GetAxis и биндинг через Project Settings⇨Input Manager.
Настало время внести корректировки в скрипт Player:
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.AI; public class Player : MonoBehaviour < NavMeshAgent navMeshAgent; public float moveSpeed; // Start is called before the first frame update void Start() < navMeshAgent = GetComponent(); > // Update is called once per frame void Update() < Vector3 dir = Vector3.zero; if (Input.GetKey(KeyCode.LeftArrow)) dir.z = -1.0f; if (Input.GetKey(KeyCode.RightArrow)) dir.z = 1.0f; if (Input.GetKey(KeyCode.UpArrow)) dir.x = -1.0f; if (Input.GetKey(KeyCode.DownArrow)) dir.x = 1.0f; navMeshAgent.velocity = dir.normalized * moveSpeed; >>
По примеру персонажа зомби при помощи Start получена ссылка на NavMeshAgent игрока, зафиксированная в поле класса. Также её следует добавить в поле moveSpeed. Его значение доступно для редактирования сразу в области Inspector в Unity, поскольку это общедоступное поле. Такая опция будет по достоинству оценена гейм-дизайнером, если он задействован в работе над проектом.
Устанавливаем значение скорости равное 10:
Для проверки нажатия стрелок на клавиатуре и управления траекторией движения персонажа следует использовать Input.GetKey из метода Update. В Unity использованы координаты X и Z для обозначения земли, а ось Y направлена вверх, перпендикулярно им.
Вектор движения dir сформирован, теперь его нужно нормализовать и умножить на ранее заданную скорость. Результат итерации отправляется в navMeshAgent.velocity, нужное значение будет добавлено автоматически. Нормализация нужна, чтобы вектор не был длиннее единичного, а объект двигался с равной скоростью как по диагонали, так и по прямой.
Теперь персонажи имеют одинаковую подвижность, что можно проверить при запуске игры:
Важно, чтобы камера двигалась вместе с персонажем. В этом поможет несложный скрипт, назовём PlayerCamera:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerCamera : MonoBehaviour < Player player; Vector3 offset; // Start is called before the first frame update void Start() < player = FindObjectOfType(); offset = transform.position - player.transform.position; > // Update is called once per frame void LateUpdate() < transform.position = player.transform.position + offset; >>
Главное, чтобы он был понятен. В качестве особенностей стоит отметить замену Update на LateUpdate — схожий по логике, но выполняется только после всех скриптов уровня. Эта замена используется, поскольку NavMeshAgent должен рассчитать новое расположение персонажа до перемещения камеры. В противном случае глаз будет резать эффект «подёргивания». После закрепления этого компонента за объектом Main Camera, при запуске игры, камера будет следовать за главным персонажем.
Во-первых, анимация — это красиво
После того, как персонажи игры стали подвижные, настал момент сделать их реалистичнее и привлекательнее. В этом поможет компонент Animator и инструмент Animator Controller.
Последний задаёт разные автоматически сменяемые состояния объекта, к которым привязывается определённая анимация. Чтобы применить этот инструмент к объекту, надо создать вложенную папку Animator Controller в директории Animations. Переименуем её в Zombie. Редактор примет вид:
На данном этапе состояния отсутствуют. Есть точки входа и выхода: Entry и Any State, Exit. Можно добавить несколько анимацией из ассетов:
Первая анимация, которую перетащили в область, привязана к точке начала, и будет проигрываться на старте уровня. Для перехода к другим состояниям нужно обозначить правило.
Нужно выбрать кнопку Parameters в левом верхнем углу, далее нажать на «+», выбрав параметр типа float. Новый параметр назовём speed:
Следует создать 2 перехода: Z_idle_A в Z_run и в обратную сторону, чтобы воспроизводилась анимация при значении speed больше 0.
Чтобы перейти из idle в run нужен двойной щелчок мыши по прямоугольнику Z_idle_A, выбираем Make Transition. Далее настраиваем параметры появившейся стрелки. Нужно отжать чекбокс Has Exit Time, в противном случае анимация будет воспроизводиться не по нашему условию. Также в списке Conditions необходимо выбрать «+», чтобы значение speed было больше 0.
Аналогичный алгоритм при переходе в обратную сторону. Теперь условие speed принимает значение меньше 0.0001. Параметр float пока не проверен на равенство:
Контроллер переместим мышью в соответствующее поле компонента Animator к объекту Zombie:
Поскольку MovementAnimator относится к игровому объекту Zombie, Animator расположен в дочернем объекте, таким образом, для получения доступа к Animator необходимо использовать стандартный метод GetComponentInChildren.
Далее необходимо отправить запрос о векторе скорости у NavMeshAgent в Update, рассчитать длину и передать результат в параметр скорости speed.
Чтобы анимировать зомби, надо добавить MovementAnimator в объект Zombie:
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.AI; public class MovementAnimator : MonoBehaviour < NavMeshAgent navMeshAgent; Animator animator; // Start is called before the first frame update void Start() < navMeshAgent = GetComponent(); animator = GetComponentInChildren(); > // Update is called once per frame void Update() < animator.SetFloat("speed", navMeshAgent.velocity.magnitude); >>
Код управления анимацией, помещённый в отдельный компонент MovementAnimation, даёт возможность не создавать контроллер игрока заново, а скопировать уже созданный для зомби. Чтобы скопировать, следует выбрать файл Zombie и нажать горячие клавиши Ctrl+D. Нужно внести изменить анимации на m_idle_А и m_run.
Потребуется ещё ряд дополнений
В класс Zombie добавим несколько строк.
navMeshAgent.updateRotation = false;
transform.rotation = Quaternion.LookRotation(navMeshAgent.velocity.normalized);
В NavMeshAgent задан такой угол поворота, что персонаж с задержкой во времени реагирует на изменение траектории движения. Добавив эти 2 строчки, можно избавиться от такого недочёта: первая строка передаёт NavMeshAgent сигнал о снятии управления поворотом (сделаем это сами); вторая — назначает поворот в сторону по вектору движения.
Важно!
Чтобы назначить поворот объекта, в 3D-графике используются эйлеровы углы, матрицы поворота или кватернионы. Первые 2 подвержены эффекту шарнирного замка (Gimbal Lock) и часто не удобны в работе, поэтому в данном примере использован кватернион. Даже при использовании матриц и углов Эйлера в Unity, они всё равно хранятся в кватернионах. В остальном, инструментарий движка настолько удобен, что позволяет разработчику не вникать в математические тонкости.
Вижу цель, вижу препятствия
Главный герой наконец-то может спастись бегством. Однако, речь шла о зомби-апокалипсисе — от толпы долго убегать не получится. Нужно отстреливаться, благо, пистолет в руках персонажа-полицейского уже имеется.
Размещаем на плоскости земли курсор под управлением мыши, чтобы игрок мог выбирать цель перед выстрелом. На мониторе курсор перемещается в 2D-пространстве, а в игровой сцене трёхмерное пространство. При этом играющий видит уровень через глаз, где в одной точке собираются все лучи света. После их объединения получается пирамида видимости:
Человеческое зрение улавливает только элементы, попавшие в эту пирамиду. Система автоматически усекает пирамиду ближней и дальней плоскостями. Ближняя плоскость (окрашена жёлтым) находится со стороны экрана, который физически не может отображать элементы, расположенные к наблюдателю ближе него. Дальняя плоскость отсекается, поскольку ресурсы компьютера ограничены — невозможно продлить луч в бесконечность.
Чтобы определить объект, на который указывает курсор, нужно выпустить из точки его расположения луч от ближней плоскости к дальней. С точки зрения играющего, тем самым объектом станет первый, с которым пересечётся луч.
Задействуя метод Raycast из класса Physics, можно выстроить луч, найти его пересечения с объектами на уровне. Он определит пересечения со всеми объектами, когда для нас важно, чтобы курсор передвигался по земле. Нужно задать в Unity ограниченный набор объектов для поиска (например, только плоскость земли).
Выделив игровой объект, можно увидеть вверху инспектора выпадающий список Layer, начально значение которого Default. В списке нам интересен пункт Add layer…, предназначенный для редактирования слоёв. Нужно добавить слой с
названием Ground:
Всем плоскостям земли в сцене нужно назначить слой Ground, что позволит указать в скрипте метод Physics.Raycast для реализации проверок пересечений.
Далее перетащим спрайт курсора из ассетов в сцену (пример: Spags Assets⇨Textures⇨Demo⇨white_hip⇨white_hip_14):
Курсору добавлен поворот вокруг оси X на 90° (пусть лежит на земле), масштаб: 0.25, Y = 0.01. Значение Y задано с целью избежать эффект Z-fighting. Для определения близости объектов к камере, видеокартой производятся расчёты с плавающей точкой, и если задать значение равное 0 для курсора и для земли, то они начнут «спорить». В итоге курсор будет частично просвечиваться и мерцать при перемещении. Значение 0.01 оптимально, чтобы сократить оплошности в расчетах видеокарты, при этом визуально не даёт ощущение, что курсор парит над землёй.
Далее назовём объект Cursor, добавим скрипт с аналогичным именем и следующим кодом:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Cursor : MonoBehaviour < SpriteRenderer spriteRenderer; int layerMask; // Start is called before the first frame update void Start() < spriteRenderer = GetComponent(); layerMask = LayerMask.GetMask("Ground"); > // Update is called once per frame void Update() < Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); RaycastHit hit; if (!Physics.Raycast(ray, out hit, 1000, layerMask)) spriteRenderer.enabled = false; else < transform.position = new Vector3(hit.point.x, transform.position.y, hit.point.z); spriteRenderer.enabled = true; >> >
Редактор Unity для изображения курсора применяет компонент SpriteRenderer, поскольку это двумерный рисунок (спрайт). Чтобы управлять включением компонента, получаем ссылку на него в Start.
В этом же методе надо преобразовать ранее созданное имя слоя Ground в битовую маску, поскольку Unity в процессе поиска пересечений пользуется битовыми масками для фильтрации объектов, а метод LayerMask.GetMask возвращает битовую маску, соответствующую указанному слою.
Получив доступ к главной камере уровня через Camera.main в методе Update, даём команду преобразовать координаты мыши (которые получены с помощью Input.mousePosition) в 3D-луч. Этот трёхмерный объект надо передать в метод Physics.Raycast и проверить пересечения с объектами в сцене. Unity просит обозначить максимальное расстояние, значение 1000 подойдёт.
Если луч и объект не пересеклись, то отключаем курсор с помощью SpriteRenderer. В противоположной ситуации перемещаем курсор в место пересечения. От точки пересечения перенимаем значения координат X и Z, а значение координаты Y не стоит менять, чтобы не получить эффект Z-fighting.
Далее к объекту Cursor добавим компонент Cursor.
Самое время дополнить скрипт Player. Сперва нужно добавить поле Cursor cursor. После допишем несколько строк в Start:
В метод Update нужно добавить код, чтобы персонаж игрока поворачивал в нужную сторону вслед за курсором:
Vector3 forward = cursor.transform.position - transform.position; transform.rotation = Quaternion.LookRotation(new Vector3(forward.x, 0, forward.z));
Координата Y по-прежнему 0.01.
Стрельба по зомби как призвание
Главный герой теперь видит атакующего зомби, но ему всё также нечего противопоставить ему. Пора научиться стрелять, чтобы выжить в тяжёлых условиях игры. Общеизвестно, что заправский стрелок всегда пользуется трассирующими пулями.
Нужно создать новый объект Shot и добавить к нему LineRenderer. В поле Width обозначается ширина — 0.04 будет достаточно. На изображении видно, что объект имеет ярко-фиолетовый цвет — так в Unity обозначаются объекты без материала.
Материал играет важную роль в каждом трёхмерном движке, с его помощью полностью описывается наружность объекта, в том числе освещённость, текстура, шейдер.
В папку Materials положим материал под названием Yellow. Для него выберем стандартный шейдер Unlit/Color. Он не учитывает освещённость, поэтому пулю будет хорошо видно.
Применяем жёлтый цвет к объекту:
Добавим скрипт Shot:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Shot : MonoBehaviour < LineRenderer lineRenderer; bool visible; // Start is called before the first frame update void Start() < lineRenderer = GetComponent(); > // Update is called once per frame void FixedUpdate() < if (visible) visible = false; else gameObject.SetActive(false); >public void Show(Vector3 from, Vector3 to) < lineRenderer.SetPositions(new Vector3[]< from, to >); visible = true; gameObject.SetActive(true); > >
Этот скрипт добавляем к объекту Shot.
Чтобы отображать 1 выстрел на кадр с минимумом кода, была применена хитрость. Во-первых, применён не Update, а FixedUpdate, которому присуща определённая периодичность вызова (по умолчанию её значение равно 60 кадров в секунду). Во-вторых, введена переменная visible с значением true во время выведения выстрела на экран. В следующем цикле FixedUpdate значение переменной меняется на false, и соответственно объект выстрела перестаёт отображаться. Эта логическая переменная работает как счётчик от 1 до 0.
Используем метод gameObject.SetActive, чтобы выключить объект. Он включает или выключает игровой объект, на котором расположен интересующий нас компонент. Отключенные объекты не выводятся на экран, а для их компонентов не вызываются методы. Благодаря этому методу действия персонажа выглядят логично — выстрел не видно, когда герой не стреляет.
В скрипте Player используем публичный метод Show для отображения пули при выстреле. Перед этим, чтобы выстрел производился из верного отверстия, нужно определить координаты дула оружия. После того, как в трёхмерной модели героя нашли объект Bip001⇨Bip001Pelvis⇨Bip001 Spine⇨Bip001 R Clavicle⇨Bip001 R UpperArm⇨Bip001 R Forearm⇨Bip001 R Hand⇨R_hand_container⇨w_handgun, нужно добавить в него «дочку» GunBarrel, расположив максимально близко к дулу.
Теперь скрипт Player дополним следующими полями:
Shot shot; public Transform gunBarrel; В Start скрипта Player впишем: shot = FindObjectOfType(); В Update тоже: if (Input.GetMouseButtonDown(0))
Подобно moveSpeed, публичное поле gunBarrel доступно также в Инспекторе. Пора назначить полю ранее созданный игровой объект:
Теперь при запуске игры персонаж может отстреливаться от зомби.
Но выстрелы не уничтожают зомби, а пролетают сквозь него. Это предсказуемо, поскольку в коде выстрела не отслеживается попадание в цель.
Исправить это довольно просто — в классе Player между строками var to = … и shot.Show(…) допишем строки:
var direction = (to - from).normalized; RaycastHit hit; if (Physics.Raycast(from, to - from, out hit, 100)) to = new Vector3(hit.point.x, from.y, hit.point.z); else to = from + direction * 100;
Чтобы луч вылетал из дула пистолета, и можно было определить факт его пересечение с другими объектами в сцене, используется Physics.Raycast.
Однако, создатели ассета добавили объектам сцены коллайдер, кроме персонажей, поэтому пуля по-прежнему будет пролетать через зомби. Исправим это упущение.
Коллайдер является компонентом для определения столкновений объектов в сцене, обычно имеет простую геометрическую форму (куб, сфера, например). Точность столкновений при этом невысока, зато формулы пересечений простые и не требуют сложных вычислений. В случаях, когда точность важнее производительности, можно использовать MeshCollider. Нам подойдёт пока стандартный компонент CapsuleCollider:
Пуля больше не пролетает сквозь зомби, но всё ещё не убивает его.
Зомби — сдохни или умри!
Первым делом в Animation Controller зомби нужно добавить анимацию смерти. Перетаскиваем туда саму анимацию AssetPacks⇨ToonyTinyPeople⇨TT_demo⇨animation⇨zombie⇨Z_death_A. Параметр died с типом trigger создаётся для её активации. Триггер, в отличие от других параметров, выступают как вызов функции, их значение откатывается к начальному после выполнения перехода. Игрок одинаково успешно может убить как идущего зомби, так и застывшего на месте, поэтому переход следует добавить из состояния Any State:
Дополним скрипт Zombie следующими полями:
CapsuleCollider capsuleCollider; Animator animator; MovementAnimator movementAnimator; bool dead;
В Start класса Zombie внесём:
capsuleCollider = GetComponent(); animator = GetComponentInChildren(); movementAnimator = GetComponent();
Добавим проверку в начале метода Update:
if (dead) return;
Шутер для ПК Unity 5 Урок 3 Стрельба из оружие арбалет от первого лица С#
Привет друзья! Сегодня в уроке я вам покажу гайд как: сделать выстрел из оружия от первого лица ? Ссылка на скрипт Научимся писать в скрипте C#.. Input.GetButtonDown («Fire1») Instantiate Vector3.forward Translate Time.deltaTime в Unity. Как создать игру на юнити.Проект игры на юнити от а до я #игра #игры #game #games Virtual Shooting (Виртуальный тир); Шутер Удачный выстрел из 17 века #fps #shooter #шутер Позитив добавляем к коммент! Ставь лайк, если тебе понравилось видео и урок. Подписывайся на канал! — Уроки от #СергеяХоббиток Лучше закреплять материал быстрее начать делать свои игры на Unity. Новый сайт молодой Все о Unity https://allunity3d.ucoz.net Ваши вопросы по урокам можете задавать на форуме Где нас можно найти на Форуме https://allunity3d.ucoz.net/forum/ Дополнительные уроки из Каталогов статей можно найти на сайте: https://allunity3d.ucoz.net/publ/ Донат на новые уроки по юнити: ЯНДЕКС КОШЕЛЕК 41001822998564 https://yoomoney.ru/to/41001822998564 Подержи проект QIWI деньги https://qiwi.com/n/SERGEIHOBBITOK Используется unity 5 для примеров уроков. Вы можете использовать другие версии. #unity #unity3d #unityуроки #unityурокинарусском #unitytutorial Лучше закреплять материал быстрее начать делать свои игры на Unity. Action (Экшен); Arcade (Аркада); Strategy (Стратегия); Adventure (Адвенчура, приключенческая игра); Educational (Образовательные игры);Quest (Квест); Interactive Fiction — IF (Интерактивная литература, ИЛ) RPG — Role Playing Game (РПГ, Ролевая игра); Fighting (Файтинг); Racing (Гонка); Simulation (Симулятор); Sports (Спортивная игра); Puzzle — Logic (Паззл, Головоломка); Tabletop (Настольные и карточные игры); Other (Остальные игры — то что никак не подходит под другие жанры). Platform (Платформер); Wargame (Варгейм); Virtual Shooting (Виртуальный тир); 3D Action (Action + Перспектива:Вид от первого/третьего лица) jRPG (RPG + Аудио-/видео-стиль: Аниме) Survival horror Гонки на выживание (Racing + Элемент жанра: Беспредел на дорогах) Shoot ’em up (Arcade + Элемент жанра: Shoot ’em up) MMORPG Он-лайн игры Теперь вы можете создать свою собственную игру с помощью Unity! Уроки по Unity от Хоббиток помогут в этом! Unity с нуля — уроки для всех. #урокиюнити #урокиunity #урокunity #программирование #дляначинающих #урок2022 #2022 Всё про Unity3d Уроки Unity. Программирование С# Тэги: unity,создание игр,как сделать игру,fps,разработка игр,юнити,игры,c#,unity3d,unity3d шутер,шутер,game,стрельба,мультиплеер,tutorial,raycast,gamedev,уроки,разработчик игр,урок,shooting,unity tutorial,shooter,games,3d шутер unity,to,how,shoot,unity 5,оружие,создание игры на unity 5,unity 3d,2d,создание игры,создание шутера,3d шутер,unity3d уроки,unity мультиплеер,unity3d уроки на руском,как создать шутер,unity уроки,сергей хоббиток,unity fps уроки,fps game unity,c# unity уроки,c# уроки,unity программирование,c# уроки для начинающих,уроки unity,c# unity3d,unity5,camera,programming,game,easy,development,beginner,games,learn,unity camera,movement,создание игр unity,unity 2022,двигаем камеру за персонажем в юнити,создать игру,как скачать юнити,игра на unity,камера в юнити,smooth camera,unity3d шутер,3d шутер unity,
Показать больше
Войдите , чтобы оставлять комментарии.
Шутер от первого лица в Unity. Часть 1 — создание проекта
В 1-й части урока создаём проект и узнаём немного теории о том, что такое Raycast.
Шутер от первого лица с использованием Raycast в Unity. За основу взят официальный урок с сайта Unity Let’s try: Shooting with Raycasts.
Добавить комментарий Отменить ответ
Наши проекты
Творческое программирование для всех! (игры и анимация на Scratch)
Бесплатные уроки для детей и взрослых
- Контакты
- Ольга Елисеева — Автор учебников, наставник, тренер, консультант
- О проекте АЭЛИТ
- Публичная оферта
- Политика конфиденциальности
- Пользовательское соглашение
- Публичная лицензия на электронные версии книг