Ударная волна / 2D Explosion Force

Для трехмерной физики в Unity, есть специальный метод, для создания эффекта ударной волны. То есть, достаточно просто придать Rigidbody необходимую силу. Но для двухмерной физики, аналога AddExplosionForce почему-то нет. Решением данной проблемы мы и займемся. В принципе, задача не сложная, но для новичка, это может создать некоторые трудности. Однако, мы будет создать не просто эффект волны, попробуем его улучшить, а именно, добавим такую фишку, что если объект, допустим, персонаж, находится за стеной, а с другой стороны происходит взрыв, то он никак не навредит нашему герою.

Добавим на сцену небольшой скрипт:

using System.Collections;
using UnityEngine;

public class ExplosionForce2D : MonoBehaviour {

	private enum Mode {simple, adaptive}
	[SerializeField] private Mode mode;
	[SerializeField] private float radius;
	[SerializeField] private float power;
	[SerializeField] private LayerMask layerMask;

	void Explosion2D(Vector3 position)
	{
		Collider2D[] colliders = Physics2D.OverlapCircleAll(position, radius, layerMask);

		foreach(Collider2D hit in colliders)
		{
			if(hit.attachedRigidbody != null)
			{
				Vector3 direction = hit.transform.position - position;
				direction.z = 0;

				if(CanUse(position, hit.attachedRigidbody))
				{
					hit.attachedRigidbody.AddForce(direction.normalized * power);	
				}
			}
		}
	}

	bool CanUse(Vector3 position, Rigidbody2D body)
	{
		if(mode == Mode.simple) return true;

		RaycastHit2D hit = Physics2D.Linecast(position, body.position);

		if(hit.rigidbody != null && hit.rigidbody == body)
		{
			return true;
		}

		return false;
	}

	void Update()
	{
		if(Input.GetMouseButtonDown(0))
		{
			Explosion2D(Camera.main.ScreenToWorldPoint(Input.mousePosition));
		}
	}
}

Итак, метод Explosion2D создает эффект взрыва, с ним же, мы отравляем позицию, где должен быть взрыв. Настроить можно радиус и силу взрыва, дополнительно есть возможность фильтровать объекты по маске слоя. Кроме этого, у нас имеются два режима Simple и Adaptive. В режиме Simple воздействие на объект будет вне зависимости от окружения. А в режиме Adaptive, с начало происходит проверка, пускаем луч, от центра взрыва и до цели, если луч встречается с проверяемым объектом, то телу придается сила, если-же луч натыкается на какое-нибудь препятствие, то с целью ничего не происходит.



Подобное можно легко прикрутить и к трехмерной физике, тогда если в игрока бросить гранату, а он спрячется за стеной, с ним ничего не произойдет. Простая и полезная вещь для любого шутера.

Скачать скрипты:

Внимание! Посетители, находящиеся в группе Гости, не могут скачивать файлы.
Тестировалось на: Unity 5.6.0

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

Офлайн
LDblue 19 апреля 2017
Спасибо, давно искал
Офлайн
FlayTheSky 20 апреля 2017
Привет всем! Насчет волны, конкретнее эффекты. Как реализовать такой красивый эффект как на гифке?
http://www.ant-karlov.ru/formidable/uploads/10068-z4_pic07.gif
Может статью об этом?
Офлайн
Light 20 апреля 2017
FlayTheSky, публикация по этой теме будет.
Офлайн
LDblue 20 апреля 2017
Light, сделай урок по созданию записок
Офлайн
Light 20 апреля 2017
LDblue, распиши конкретней, а там видно будет.
Офлайн
LDblue 20 апреля 2017
Light, допустим лежит записка с текстом (canvas или куб с текстурой бумаги), подходишь к нему и нажимаешь кнопку, открывается записка.

пример:





(код не мой, я просто подстроил под себя)
Офлайн
Light 20 апреля 2017
LDblue, в качестве примера, нужно делать понятное описание сути вопроса или давать отсылку к конкретной игре, или показывать что-то на простеньком рисунке.
Офлайн
Короче лежит на столе объект(записка) с триггером и Canvas UI Text(его скрываем) с темной панелью на весь экран(можно прикрутить анимации плавного появления(исчезновение заменой Speed = -1)). При контакте с персонажем(OnCollisionEnter2D) при нажатии на специальную кнопку(обычно E в ПК) ставим игру на паузу и делаем канвас видимым(или запускаем анимацию появления/исчезновения(можно, и нужно даже через bool). Вот так я вижу алгоритм действий. Норм? sweat_smile Сорян, если что, пытаюсь помочь

UPD: можно наверно создать шаблон канваса(чтоб слишком много объектов не создавать), и менять лишь текст внутри него
Офлайн
Stas Artemev 18 марта 2018
Как сделать например падает бомба(ForgeBomb) попадает в игрока(Player) и он отталкивается ? Т.е чтобы не мышкой активировалась а при попадании бомбы в игрока(Player) ?
Офлайн
Light 19 марта 2018
Stas Artemev, заменить Update на триггер, например:

using System.Collections;
using UnityEngine;
[RequireComponent(typeof(CircleCollider2D))]
[RequireComponent(typeof(Rigidbody2D))]
public class ExplosionForce2DTrigger : MonoBehaviour {

	private enum Mode {simple, adaptive}
	[SerializeField] private Mode mode;
	[SerializeField] private float radius = 5;
	[SerializeField] private float power = 100;
	[SerializeField] private LayerMask layerMask = -1;
	private CircleCollider2D coll;

	void OnValidate()
	{
		coll = GetComponent<CircleCollider2D>();
		coll.isTrigger = true;
	}

	void Explosion2D(Vector3 position)
	{
		Collider2D[] colliders = Physics2D.OverlapCircleAll(position, radius, layerMask);

		foreach(Collider2D hit in colliders)
		{
			if(hit.attachedRigidbody != null)
			{
				Vector3 direction = hit.transform.position - position;
				direction.z = 0;

				if(CanUse(position, hit.attachedRigidbody))
				{
					hit.attachedRigidbody.AddForce(direction.normalized * power);	
				}
			}
		}
	}

	bool CanUse(Vector3 position, Rigidbody2D body)
	{
		if(mode == Mode.simple) return true;

		RaycastHit2D hit = Physics2D.Linecast(position, body.position);

		if(hit.rigidbody != null && hit.rigidbody == body)
		{
			return true;
		}

		return false;
	}

	void OnTriggerEnter2D(Collider2D other)
	{
		Explosion2D(transform.position);
	}
}
Офлайн
Stas Artemev 19 марта 2018
Спасибо, большое.
Информация
Посетители, находящиеся в группе Гости, не могут оставлять комментарии к данной публикации.
  • Яндекс.Метрика