Стрельба и система повреждений

Обычно в играх, для реализации стрельбы, используется два варианта. Первый, для тех случаев, когда нужно, чтобы пулю можно было видеть, то есть низкая скорость движения объекта. Например, если это какой-нибудь снаряд, либо нечто энергетическое, наподобие сгустка плазмы. Во втором варианте, когда скорость пуль высокая (автоматы, пистолеты и прочее) и их не видно. Хотя визуализация может быть, но учитывается не попадание пули в цель, а «попадание» прицела на цель и нажатие клавиши выстрела. Иначе говоря, в первом случаи, нужно создавать объекты и задавать им траекторию движения, в другом, нужно лишь передать цели переменную.

Сделать всё это в принципе не сложно.
Для начала, нам понадобится прицел для нашего оружия. То есть указатель по центру экрана. Находим или рисуем подходящую нам иконку прицела, с прозрачным фоном. Затем, добавляем на сцену GameObject -> UI -> Image и указываем в качестве источника изображения нашу иконку. Осталось разместить прицел по центру и отрегулировать размер. Внимание! Скрипт стрельбы, нужно вешать именно на этот UI объект.

Напишем небольшой скрипт учета повреждений EnemyHealth и цепляем его на цель:

using UnityEngine;
using System.Collections;

public class EnemyHealth : MonoBehaviour {

	public float HP = 10;

	public void AddDamage(float damage)
	{
		HP -= damage;
		if(HP <= 0)
		{
			Destroy(gameObject);
		}
	}
}

Тут всё просто, есть "здоровье" и одна публичная функция.

Теперь, займемся скриптом стрельбы, название может быть каким угодно:

Пистолеты, пулеметы и похожий огнестрел

Объявляем необходимы переменные:

public float damage = 1;
public float timeout = 0.2f;
public string[] targetTags = {"Target_1", "Target_2"};
private float curTimeout;

damage - сколько HP будет отнимать одно попадание.

timeout - темп стрельбы.

targetTags - здесь надо указать теги объектов, у которых будет скрипт EnemyHealth. Например, в игре могут быть различные типы врагов, с разными тегами для определенного взаимодействия. Поэтому, проще использовать текстовый массив, вместо копирования кусков кода.

Далее:

void Update() 
{
	RaycastHit hit;
	Ray ray = Camera.main.ScreenPointToRay(transform.position);
	if (Physics.Raycast(ray, out hit))
	{
		if(Input.GetMouseButton(0))
		{
			foreach(string currentTag in targetTags)
			{
				if(currentTag == hit.transform.tag)
				{
					curTimeout += Time.deltaTime;
					if(curTimeout > timeout)
					{
						curTimeout = 0;
						hit.transform.GetComponent<EnemyHealth>().AddDamage(damage);
					}
				}
			}
		}
		else
		{
			curTimeout = timeout + 1;
		}
	}
}

Так как прицел у нас по центру экрана. Соответственно от центра пускаем луч и при нажатой ЛКМ, если луч попадает на объект у которого есть тег, как в массиве, то отправляем переменную damage.

Плазменное оружие и тому подобное


Так, переменные:

public Rigidbody bullet;
public Transform gunPoint;
public int bulletSpeed = 10;
public float timeout = 0.5f;
private float curTimeout;

bullet - префаб снаряда, о котором поговорим позже.

bulletSpeed - скорость пули.

gunPoint - точка, где будут появятся снаряды. То есть создаем пустой объект, затем его надо сделать дочерним модели оружия и разместить так, чтобы этот объект был там-же, где и дуло оружия. Получится, что пули, как бы вылетают из дула.

Стрельба и система повреждений

Продолжим:

void Update() 
{
	if(Input.GetMouseButton(0))
	{
		curTimeout += Time.deltaTime;
		if(curTimeout > timeout)
		{
			curTimeout = 0;
			Rigidbody bulletInstance = Instantiate(bullet, gunPoint.position, Quaternion.identity) as Rigidbody;
			bulletInstance.velocity = gunPoint.forward * bulletSpeed;	
		}
	}
	else
	{
		curTimeout = timeout + 1;
	}
}

Скрипт создает объект пули и задет вектор движения, от точки gunPoint - до точки, куда "смотрит" прицел. В общем, как и должно быть.

О префабе пули. На нем обязательно должно быть три компонента: Collider (в режиме триггера), Rigidbody (с отключенной гравитацией) и скрипт Bullet.

Содержание скрипта пули:

using UnityEngine;
using System.Collections;

public class Bullet : MonoBehaviour {

	public float damage = 1;
	public string[] targetTags = {"Target_1", "Target_2"};

	void OnTriggerEnter(Collider coll)
	{
		foreach(string currentTag in targetTags)
		{
			if(currentTag == coll.transform.tag)
			{
				coll.transform.GetComponent<EnemyHealth>().AddDamage(damage);
			}
		}
		Destroy(gameObject);
	}
}

Комментариев 6

Офлайн
TheRobin 13 марта 2019
ошибка error CS1525: Unexpected symbol `end-of-file' как исправить ?
Офлайн
StefanVanhazen 18 ноября 2018
а как сделать, чтоб он стрелял не от мыши , а от определенного объекта на сцене? а то так не работает:
Скрипт на персонаже
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class DamageControll : MonoBehaviour {
string _up = "Up";
bool up;
public float damage = 1;
public float timeout = 0.2f;
public string[] targetTags = { "Enemy" };
public float curTimeout;
// Update is called once per frame
void Update () {


transform.position = new Vector2(transform.position.x, transform.position.y);
GetInput();
RaycastHit hit;
Ray ray = new Ray (transform.position, Vector2.up);
if (Physics.Raycast (ray,out hit))
{
if (up){
foreach (string currentTag in targetTags)
{
if (currentTag == hit.transform.tag)
{
curTimeout += Time.deltaTime;
if (curTimeout > timeout)
{
curTimeout = 0;
hit.transform.GetComponent<Enemy>().addDamage(damage);
}
}
}
}
else
{
curTimeout = timeout + 1;
}
}
}
void GetInput()
{
up = Input.GetButton(_up);
}
}
скрипт на враге
using System.Collections;
using System.Collections.Generic;
using UnityEngine;


public class Enemy : MonoBehaviour
{

public float hp = 3;

public void addDamage(float damage)
{
hp -= damage;
if (hp <= 0)
gameObject.SetActive(false);


}


}
Офлайн
TheRobin 9 ноября 2018
Ааа как сделать перезарядку ?
Офлайн
qqshka 19 июля 2018
Как скачать?
Офлайн
Light 8 мая 2018
userHs, внес изменения в пример с Rigidbody, теперь должно быть нормально.
Офлайн
userHs 8 мая 2018
Возникла проблема. Если вращение персонажа по Y отлично от 0 то идет жеткое смещение пули в сторону при стрельбе физическим телом.
Информация
Посетители, находящиеся в группе Гости, не могут оставлять комментарии к данной публикации.
  • Яндекс.Метрика