Область видимости или поле зрения, для бота

Сканирование области для поиска указанной цели, или точнее, допустим, у нас есть определенный угол зрения бота и область внутри этого угла нужно просканировать. В роли сканера – луч , соответственно понадобится пустить несколько лучей в пределах угла. Пускать луч в каждую точку нет никакого смысла, к тому же это много ресурсов потребует. Нужно сделать несколько лучей и равномерно распределить их по области, в результате должно быть так, чтобы между лучами нельзя было спрятаться, иначе говоря, чтобы без слепой зоны. Вот такая задача у нас получается. А задумывалась всё изначально под игру с видом сверху, где нужно избегать встреч с охранниками, при учете того, что у них есть поле зрения.


Так, скрипт RayScan:

using UnityEngine;
using System.Collections;

public class RayScan : MonoBehaviour {
	
	public string targetTag = "Player";
	public int rays = 6;
	public int distance = 15;
	public float angle = 20;
	public Vector3 offset;
	private Transform target;

	void Start () 
	{
		target = GameObject.FindGameObjectWithTag(targetTag).transform;
	}

	bool GetRaycast(Vector3 dir)
	{
		bool result = false;
		RaycastHit hit = new RaycastHit();
		Vector3 pos = transform.position + offset;
		if (Physics.Raycast (pos, dir, out hit, distance))
		{
			if(hit.transform == target)
			{
				result = true;
				Debug.DrawLine(pos, hit.point, Color.green);
			}
			else
			{
				Debug.DrawLine(pos, hit.point, Color.blue);
			}
		}
		else
		{
			Debug.DrawRay(pos, dir * distance, Color.red);
		}
		return result;
	}
	
	bool RayToScan () 
	{
		bool result = false;
		bool a = false;
		bool b = false;
		float j = 0;
		for (int i = 0; i < rays; i++)
		{
			var x = Mathf.Sin(j);
			var y = Mathf.Cos(j);

			j += angle * Mathf.Deg2Rad / rays;

			Vector3 dir = transform.TransformDirection(new Vector3(x, 0, y));
			if(GetRaycast(dir)) a = true;

			if(x != 0) 
			{
				dir = transform.TransformDirection(new Vector3(-x, 0, y));
				if(GetRaycast(dir)) b = true;
			}
		}
	
		if(a || b) result = true;
		return result;
	}

	void Update ()
	{	
		if(Vector3.Distance(transform.position, target.position) < distance)
		{
			if(RayToScan())
			{
				// Контакт с целью
			}
			else
			{
				// Поиск цели...
			}
		}
	}
}

По умолчанию, мы ищем объект с тегом Player, как только цель приближается на расстояние видимости distance, тогда пускаем лучи. Если потребуется сместить центр из которого выпускаются лучи, используем offset. Число лучей rays будет умножено на два, поэтому имейте это ввиду. Если задействовать одновременно слишком много лучей, то просядит fps. Угол обзора, регулируется через angle.



Для удобства настройки, каждый луч подсвечен в зависимости от состояния. Красный - никуда не попадает. Синий - контакт с коллайдером. Зеленый - контакт с целью. Чтобы видеть подсветку, включите Gizmos, на панели плеера Unity.

Область видимости или поле зрения, для бота

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

Офлайн
tduk 22 ноября 2016
вы просто лучшие!!!!! Суперский сайт,очень благодарен!!!
Офлайн
mxstore 16 октября 2017
помогите перестроить к 2д
рэйкаст 2д пишет ошибку тут if (Physics.Raycast(pos, dir, hit, distance))
Аргумент 3: не удается преобразовать из "UnityEngine.RaycastHit2D" в "float".
Информация
Посетители, находящиеся в группе Гости, не могут оставлять комментарии к данной публикации.
  • Яндекс.Метрика