Как и всегда, есть несколько путей решения проблемы. Какой выбрать, решать вам. Например, Вы хотите что-бы пуля была большой и летела медленно, тогда ваш вариант это физическая пуля. Нагрузка больше из-за расчетов физики, но эффект броска снежка или камня есть. А вот если вы делаете автомат и пуль много, их все равно не видно, можно сделать через рейкаст, что собственно все и делают, а физику полета пули рассчитывают заранее, видим мы только эффект от прилетевшей пули, иногда с эффектом трастера.
Для начала рассмотрим все в теории, а потом уже возьмемся за реализацию и тестирование.
Теория
Физическое тело в виде снаряда
Итак, у нас есть задача бросить камень, надеюсь не в меня) Для этого делается следующее:
- В момент нажатия на ЛКМ создается объект
- Мы получает этот объект и толкаем его в нужном направлении
- Далее движок считает все за нас, мы только смотрим
- Возможно создаем эффекты приземления
Все просто. Часто именно такой подход и необходим. Так можно симулировать, достаточно медленные снаряды, которые не часто вылетают из оружия. К примеру, снежки, камни, ядра пушек, картофель из пататогана). Проблемы начинаются когда необходимо создать что-то дальнобойные или скорострельное.
При быстром движении такие снаряды могут пролетать сквозь объекты. Способ обхода этого есть, но нагрузка на процессор чуть выше обычного физического тела, а на дальнем расстоянии снаряд все равно особо не видно, так зачем грузить процессор?
Если же нам хочется создать много объектов, проблемы в принципе такие же. Они могут пролетать сквозь объекты, грузить процессор так же скорострельность оружия ограничена размером объекта, так как он будет задевать предыдущий снаряд и они полетят ни так как хотелось бы.
Как же быть? Для таких целей обычно используют рейкаст
Рейкаст для реализации выстрела
В простейшем случае работает это таким образом:
- Мы выпускаем луч в нужном направлении
- Определяем куда он попадет
- рисуем эффект попадания или делаем что то еще
Для расчета падения пули можем провести расчет по скорости и дальности, затем опустив попадание ниже. У такого подхода есть свой минус. Пуля может пролететь сквозь стену если мы ее не просчитаем сами.
Как решить данную проблему?
Можно после получения конечной точки пустить еще один луч и проверить соприкосновения еще раз, это не совсем правильно но не так затратно по ресурсам.
Можно запустить симуляцию всего полета "на паузе". Расчет требует времени и соответственно ресурсов, однако точно просчитает полет пули. Это почти так же как и в варианте с физическим объектом, но расчет ведется отдельно от текущего времени и выдается только результат.
Так же выполняется создание обьекта и его пинок в нужном направлении но с игнорированием реального времени.
Либо по школьной физике просчитываем полет тела сами, но зачем? Все равно каждую точку проверять нужно на столкновения.
Практика
Физический снаряд
Начнем практику с кидания камней в стену, стену сделаем разрушаемой, для большего веселья.
Стрелять будем в точку, без поворота камеры.
using UnityEngine;
public class ShotToClick : MonoBehaviour
{
public GameObject Bullet;
public float Power;
void Update()
{
if (Input.GetMouseButtonDown(0)){
GameObject b = Instantiate(Bullet, transform.position, transform.rotation);
b.GetComponent<Rigidbody>().AddForce(Vector3.forward * Power, ForceMode.Impulse);
}
}
}
Тут все просто, как и описывалось выше, создается объект и мы его пинаем вперед, все.
Путь луча
Принцип описан выше, сцена та же самая, код чуть ниже. Для Визуализации я буду создавать "пулю" в точке соприкосновения луча и объекта. В реальном проекте, там нужно оставлять следы от пуль, искры, осколки, все что захотите.
using UnityEngine;
public class ShotToClickRaycast : MonoBehaviour
{
public GameObject Bullet;//только для визуализации
public float Power;
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonDown(0)){
Ray ray = new Ray(transform.position, transform.forward);
RaycastHit hit;
if (Physics.Raycast(ray,out hit)){
hit.rigidbody.AddForceAtPosition(ray.direction * Power, hit.point, ForceMode.Impulse);
Instantiate(Bullet, hit.point, transform.rotation);
}
}
}
}
При клике мгновенно появляется наш снаряд в месте куда он должен был попасть. Если у нас не большая локация, пуля летит быстро, то можно пренебречь скоростью пули и стрелять прямо так.
Так же можно добавить поведение оружия. Отдача, точность, разброс и тд. Тут уже полностью от ваших хотелок.
Итоги
В данной статье я привел лишь примеры того как можно сделать выстрелы в unity. Надеюсь она вам поможет определиться как действовать дальше и у вас получиться хорошая стрелялка =)
Скачать можно тут.