Скрипт оружия для Unity

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


Подготовим сцену Unity. Необходимо добавить GameObject -> UI -> Image, устанавливаем по центру и в качестве изображение, ставим какой-нибудь спрайт прицела, и переименуем Cursor. Теперь, на этот курсор вешаем скрипт оружия, под именем ImpulseGun:

using UnityEngine;
using System.Collections;

public class ImpulseGun : MonoBehaviour {

	public static bool impulseActive;
	public int impulseForce = 1500;
	public float impulseRadius = 15f;
	public int impulseCount = 3;
	public float impulseDistance = 7f;
	public float maxDistance = 30f;
	public GameObject impulseExplosion;
	
	void Start () 
	{
		impulseActive = false;
	}
	
	void Update ()
	{
		RaycastHit hit;
		Ray ray = Camera.main.ScreenPointToRay(transform.position);
		if (Physics.Raycast(ray, out hit))
		{
			if(Input.GetMouseButtonDown(0))
			{
				if(hit.rigidbody)
				{
					if(hit.distance < impulseDistance)
					{
						hit.rigidbody.AddForce(ray.direction * impulseForce/hit.rigidbody.mass);
					}
					else
					{
						Debug.Log("Объект в не зоне действия!");
					}
				}
			}
			else if(Input.GetMouseButtonDown(1))
			{
				if(!impulseActive)
				{
					if(hit.distance < maxDistance)
					{
						GameObject clone = Instantiate(impulseExplosion, hit.point, Quaternion.identity) as GameObject;
						clone.GetComponent<ImpulseGunExplosion>().power = impulseForce;
						clone.GetComponent<ImpulseGunExplosion>().count = impulseCount;
						clone.GetComponent<ImpulseGunExplosion>().radius = impulseRadius;
					}
					else
					{
						Debug.Log("Превышен лимит дистанции!");
					}
				}
				else
				{
					Debug.Log("Оружие активно!");
				}
			}
		}
	}
}

impulseActive - если второй режим оружия активен, то еще один активировать нельзя, чтобы эффекты не накладывались друг на друга.

impulseForce - сила, которая будет применяться на объект, также используется для второго режима стрельбы.

impulseRadius - область действия взрыва.

impulseCount - количество повторов толчок/притяжение.

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

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

impulseExplosion - префаб «снаряда».

Делаем префаб. Это может быть любой объект с какой-нибудь анимацией, или же просто пустышка. Главное чтобы не было Collider-а, либо он должен быть в режиме триггера. Иначе будет мешать движению других коллайдеров. В общем, к префабу прицепляем скрипт ImpulseGunExplosion:

using UnityEngine;
using System.Collections;

public class ImpulseGunExplosion : MonoBehaviour {

	public float radius;
	public int power;
	public int count;
	private Vector3 explosionPos;
	private Collider[] colliders;
	private bool impulse;

	void Start() 
	{
		ImpulseGun.impulseActive = true;
		explosionPos = transform.position;
		colliders = Physics.OverlapSphere(explosionPos, radius);
		StartCoroutine(Wait());
	}

	void Explosion()
	{
		foreach (Collider hit in colliders) 
		{
			if (hit.GetComponent<Rigidbody>() && !hit.CompareTag("Player"))
				hit.transform.GetComponent<Rigidbody>().AddExplosionForce(hit.GetComponent<Rigidbody>().mass * power, explosionPos, radius);
		}
		ImpulseGun.impulseActive = false;
		Destroy(gameObject);
	}

	IEnumerator Wait()
	{
		impulse = true;
		yield return new WaitForSeconds(0.5f);
		StartCoroutine(ImpulseCount());
	}

	IEnumerator ImpulseCount()
	{
		impulse = false;
		foreach (Collider hit in colliders) 
		{
			if (hit.GetComponent<Rigidbody>() && !hit.CompareTag("Player"))
			{
				hit.GetComponent<Rigidbody>().Sleep();
				hit.GetComponent<Rigidbody>().WakeUp();
				hit.transform.GetComponent<Rigidbody>().AddExplosionForce(hit.GetComponent<Rigidbody>().mass * 1000, explosionPos, radius);
			}
		}
		yield return new WaitForSeconds(0.5f);
		if(count > 0)
		{
			count--;
			StartCoroutine(Wait());
		}
		else
		{
			Explosion();
		}
	}

	void FixedUpdate() 
	{
		if(impulse)
		{
			foreach (Collider hit in colliders) 
			{
				if (hit.GetComponent<Rigidbody>() && !hit.CompareTag("Player"))
				{
					Vector3 direction = hit.GetComponent<Rigidbody>().transform.position - explosionPos;
					hit.GetComponent<Rigidbody>().AddForceAtPosition(-direction.normalized * hit.GetComponent<Rigidbody>().mass * 100, explosionPos);
				}
			}
		}
	}
}

Внимание! Чтобы всё работало, персонаж которым управляет игрок, должен иметь стандартный тег Player. А главная камера, на которой будет виден прицел, должна быть с тегом MainCamera. В целом, как-бы всё. Успехов! :bully:

P.S.
ЛКМ - первый режим, ПКМ - второй.

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

Офлайн
Arik 3 мая 2016
Это все хорошо. А вот как реализовать прицел космического корабля который направлен на землю (террейн) и который берет координаты из мыши?

И еще вопрос. Как правильнее реализовать стрельбу ракетами когда определенное кол-во ракет видимы? Т.е. есть обьект и у него ракетная установка, в ней 10 ракет. Выстрелил все - досвидания. Использовать массив?
Офлайн
Light 3 мая 2016
Цитата: Arik
А вот как реализовать прицел космического корабля который направлен на землю (террейн) и который берет координаты из мыши?

Управляемый прицел? Пример можно взять от сюда.

Цитата: Arik
Использовать массив?

Просто считать, минус один, за каждый выстрел.
Офлайн
Arik 4 мая 2016
Представьте, что летит вертолет, а прицел следит за координатами мышки. При этом ползая по земле и огибая все её неровности.
Офлайн
Light 4 мая 2016
Arik, на эту тему будет отдельная статья.
Офлайн
Arik 4 мая 2016
Цитата: Light
Arik, на эту тему будет отдельная статья.


Скорее бы )
Офлайн
Где можно скачать проект?
Офлайн
lolgad 14 мая 2017
Автор пожалуйста объясните почему объекты со скриптом ImpulseGunExplosion проваливаются бод террейн, хотя есть колайдеры?
Офлайн
Light 15 мая 2017
lolgad, коллайдеры могут проходить сквозь друг друга, когда скорость объекта высокая, а размеры коллайдера небольшие.
Информация
Посетители, находящиеся в группе Гости, не могут оставлять комментарии к данной публикации.
  • Яндекс.Метрика