#unity3d
#unity3d
Вопрос:
Я немного искал stack overflow и Интернет, пытаясь найти решение этой проблемы, каждый раз, когда я пытаюсь использовать OnBecameVisible() или OnBecameInvisible() или TestPlanesAABB, чтобы проверить, не виден ли объект через стену, камера все еще может видеть объект через сплошную стену.
Видео проблемы здесь: https://youtu.be/3HiEugm6On8
Как вы можете видеть, если я смотрю на него, он перестает двигаться, если я поворачиваюсь, и он «выгружается» или «становится невидимым», он приближается, но если я заворачиваю за угол, все еще глядя в его сторону, он перестает двигаться, как будто я его вижу, и там нет стеныэто то, что я пытаюсь решить
это враг, который бродит вокруг, и я хочу, чтобы он двигался, только если я его не вижу, что, как я думал, было бы довольно просто, но, увы, это не так просто, как я думал
мой текущий код является базовым:
public bool IsSeen = false;
public void OnBecameVisible()
{
Debug.Log("I can now see you");
IsSeen = true;
}
public void OnBecameInvisible()
{
Debug.Log("I can't see you");
IsSeen = false;
}
это привязано к объекту, который я хочу обнаружить / не обнаружить через стены, что, как я полагаю, проверяет, доступен ли объект для просмотра камерой, которую я выбираю.
у кого-нибудь есть какие-либо идеи относительно того, как я могу это исправить / добиться?
Комментарии:
1. От
Renderer.OnBecameVisible
:Note that object is considered visible when it needs to be rendered in the Scene. It might not be actually visible by any camera, but still need to be rendered for shadows for example. Also, when running in the editor, the Scene view cameras will also cause this function to be called.
2. Думаю, чтобы избежать этого, вам придется использовать raycast
3. есть ли простой способ радиовещания на весь экран? или пределы экрана, поскольку я хочу, чтобы враг вообще не двигался, если он на экране
Ответ №1:
Как уже упоминалось, общая «проблема» с Renderer.OnBecameVisible
Обратите внимание, что объект считается видимым, когда его нужно отобразить в сцене. На самом деле он может быть не виден ни одной камерой, но его все равно нужно отобразить, например, для теней. Кроме того, при запуске в редакторе камеры просмотра сцены также вызывают эту функцию.
Так что это не совсем удобно для вас.
есть ли простой способ радиовещания на весь экран?
К сожалению, не совсем :/
Вы можете немного избежать этого, используя GeometryUtility.CalculateFrustumPlanes
, чтобы получить четыре плоскости усечения камеры. Затем вы можете проверить, действительно ли объект находится внутри усечения, используя GeometryUtility.TestPlanesAABB
var cam = Camera.main;
var planes = GeometryUtility.CalculateFrustumPlanes(cam);
var objCollider = GetComponent<Collider>();
if (GeometryUtility.TestPlanesAABB(planes, objCollider.bounds))
{
Debug.Log("I am inside the camera frustrum!");
}
else
{
Debug.Log("I am out of sight...");
}
Однако это все равно не распространяется на какой-либо другой объект, находящийся перед целевым объектом и, следовательно, фактически покрывающий его.
Вам нужно будет точно определить, что означает visible (например, какая-либо часть сетки? Достаточно ли центра объекта для тестирования? и т.д.).
Например, для тестирования только центра объекта вы можете использовать Physics.Linecast
, например,
if (GeometryUtility.TestPlanesAABB(planes, objCollider.bounds))
{
Debug.Log("I am inside the camera frustrum!");
if(Physics.LineCast(cam.transform.position, objCollider.GetComponentInChildren<Renderer>().bounds.center, out var hit)
{
if(hit.gameObject != objCollider.gameObject)
{
Debug.Log("..but something else is in the way..");
}
else
{
Debug.Log("Now you see me, muhaha!");
}
}
}
Если вы хотите, чтобы он был более точным, и была видна какая-либо часть сетки, тогда это действительно становится сложным. Вам нужно будет передать несколько ключевых точек ограничивающей рамки (например, каждый угол, центры ребер и т.д.) в зависимости от ваших потребностей.