Во время создания своей прекрасной и непревзойдённой игры мне потребовались лучи Raycast-a, так как работаю над top - down танковым шутером с механикой обнаружения противника .В интернете мало чего дельного есть, кроме документации, поэтому в этой статье разложу всё по полочкам.
Будем рассматривать работу Raycast - а в 2D пространстве на примере моего же кода. Всё работает на актуальной версии Unity, не судите код, я - любитель.
Рассматриваем куски кода, который идут по порядку:
Итак, здесь я ввожу булевые переменные для проверки данным скриптом, попал ли луч в нужный нам объект.
IsEyeContact - попадает ли луч в цель?
AimYet - может ли бот уже стрелять, довернулось ли орудие до игрока?
Также вводятся переменные объектов.
Массив target - это список объектов: точки, куда мы пускаем лучи, и объект с коллизией игрока под индексом target[0]. Все остальные точки массива расположены по периметру танка.
SpotPoint, AimPoint - точки, ИЗ которых пускаются лучи. Они находятся у противника на башне.
Далее в FixedUpdate я задаю маску этим лучам, т.е. слои объектов, которые они проходят насквозь.
-----------------------------------------------------------------------
int ignoreWeaponMask = 1 << 12;
int ignoreWeaponMask2 = 1 << 11;
int ignoreRaycastMask = 1 << 9;
int ignoreRaycastMask2 = 1 << 2;
int layerMask = ignoreWeaponMask | ignoreRaycastMask | ignoreWeaponMask2 | ignoreRaycastMask2;
layerMask = ~layerMask;
------------------------------------------------------------------------------------
Числа 12; 11; 9; 2 - номера тех слоёв, которые луч игнорирует.
Хотите добавить слой в игнор, добавляете новую переменную. Названия ignoreWeaponMask, gnoreWeaponMask2 и др. просто названия новоявленных переменных, поэтому вы можете вместо них использовать, какие вам взбредёт в голову, например:
int UselessLayer = 1 << номер слоя;
Потом мы их совмещаем их в одну переменную последними двумя строчками. Там вписываются название ранее объявленных переменных через данный символ | .
Итак, дальше можно пускать лучи.
RaycastHit2D hit0 = Physics2D.Raycast(SpotPoint.transform.position, target[0].transform.position - SpotPoint.transform.position, Mathf.Infinity, layerMask);
Я могу и пускаю сразу несколько лучей одновременно в направлении точек из массива.
---------------------------------------------------------
RaycastHit2D aiming = Physics2D.Raycast(AimPoint.transform.position, transform.TransformDirection(Vector2.up), Mathf.Infinity, layerMask);
---------------------------------------------------------------
Здесь луч пускается чётко вверх от объекта и зависит от его поворота в пространстве.
Заключительный этап. Проверка попадания
if (hit0.collider != null) //В этой строке проверяется, попал ли луч вообще в какой - либо коллайдер.
{
if (hit0.collider.gameObject == target[0]) //А в этой, является ли этим коллайдером коллайдер именно нужного нам объекта.
{
IsEyeContact = true;
}
else
{
IsEyeContact = false;
}
}
else
{
IsEyeContact = false;
}
Ну вот и всё, о чём стоит поговорить на тему рэйкаста в 2D пространстве. Надеюсь, всё было понятно и доходчиво, мне бы данная статья точно помогла) Оценивайте, пишите комментарии, в последствии постараюсь выложить ещё что - нибудь.
Ниже прикреплю полный код:
Пофантазируйте, модернизируйте и упрощайте наздоровье!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Raycast : MonoBehaviour
{
public GameObject[] target;
public bool IsEyeContact = false;
public bool AimYet = false;
public GameObject SpotPoint;
public GameObject AimPoint;
void FixedUpdate()
{
int ignoreWeaponMask = 1 << 12;
int ignoreWeaponMask2 = 1 << 11;
int ignoreRaycastMask = 1 << 9;
int ignoreRaycastMask2 = 1 << 2;
int layerMask = ignoreWeaponMask | ignoreRaycastMask | ignoreWeaponMask2 | ignoreRaycastMask2;
layerMask = ~layerMask;//инвертируем маску, теперь выбранные слои будут игнорироваться
// Cast a ray straight down.
RaycastHit2D hit0 = Physics2D.Raycast(SpotPoint.transform.position, target[0].transform.position - SpotPoint.transform.position, Mathf.Infinity, layerMask);
RaycastHit2D hit1 = Physics2D.Raycast(SpotPoint.transform.position, target[1].transform.position - SpotPoint.transform.position, Mathf.Infinity, layerMask);
RaycastHit2D hit2 = Physics2D.Raycast(SpotPoint.transform.position, target[2].transform.position - SpotPoint.transform.position, Mathf.Infinity, layerMask);
RaycastHit2D hit3 = Physics2D.Raycast(SpotPoint.transform.position, target[3].transform.position - SpotPoint.transform.position, Mathf.Infinity, layerMask);
RaycastHit2D hit4 = Physics2D.Raycast(SpotPoint.transform.position, target[4].transform.position - SpotPoint.transform.position, Mathf.Infinity, layerMask);
RaycastHit2D aiming = Physics2D.Raycast(AimPoint.transform.position, transform.TransformDirection(Vector2.up), Mathf.Infinity, layerMask);
// If it hits something...
if (hit0.collider != null || hit1.collider != null || hit2.collider != null || hit3.collider != null || hit4.collider != null)
{
if (hit0.collider.gameObject == target[0] || hit1.collider.gameObject == target[0] || hit2.collider.gameObject == target[0] || hit3.collider.gameObject == target[0] || hit4.collider.gameObject == target[0])
{
IsEyeContact = true;
}
else
{
IsEyeContact = false;
}
}
else
{
IsEyeContact = false;
}
if (aiming.collider != null)
{
if (aiming.collider.gameObject == target[0])
{
AimYet = true;
}
else
{
AimYet = false;
}
}
else
{
AimYet = false;
}
}
}