- Home /
How to RayCast a triangular field of view for my autonomous moving agent
I'm building an autonomous moving agent and using Raycast(not a must) I want to give it the ability to sense obstacles up ahead. instead of just ray casting a line from it's current position towards transfom.forward direction, I want to broaden his field of view to that of an inverted triangle like the picture
so far what I came up with is to cast two lines, which represents the border of my vision using quaternions.angleAxis
rotationRight = Quaternion.AngleAxis(30, transform.up);
rotationLeft = Quaternion.AngleAxis(-30, transform.up);
Vector3 rayR = rotationRight * transform.forward; //convert angle to a vector3
Vector3 rayL = rotationLeft * transform.forward;
if (Physics.Raycast(transform.position, rayR, out hit, minDistance)|| Physics.Raycast(transform.position, rayL, out hit, minDistance))
{
//turn around
}
while this does the job in case the obstacles where wide enough to be picked by the two lines, since I lack any central view, so I need to either stick to a small field of view or cast yet a third line in the center. how can I achieve this in a clean and more effiecient way?
while a bit old I do recall unity did a tutorial on ai like this here is a link to there video on you tube YouTube Video
Answer by Bunny83 · Jun 30, 2016 at 10:47 AM
The usual procedure to simulate a real "field of view" is to use:
Physics.OverlapSphere to get all objects within the desired radius
Filter out objects which are not in the desired view cone / frustum
Finally you can do a raycast to every enemy that's within the view area to see if you have a straight line of sight to that object.
The main problem with that approach is that you can only do the direction check with the object's origin. For long objects it's possible that it's origin is outside the view while a part of it is still inside. For that you might want to keep your two unconditional raycast at the two sides to cover that as well.
So you end up with a list of colliders / objects that are within the field of view of your agent.
@Bunny83 can you help me find out why I'm experiencing this behavior with my agent?(see gif)
link text what I tried is to sphereCast from my current position with a given radius and capture the RaycastHit, then using Vector3.dot I managed to find the angle between my agent and obstacle and if it happens to be within my field of view then time to change rotation(I'm trying to make an obstacle avoiding agent) I'll post the code
if (Physics.SphereCast(transform.position,radius,transform.forward,out hit,2, block)) {
//find angle between my agent and the hit is it in my field of view
float angle = Vector3.Dot(transform.forward, hit.point.normalized);
float degree = $$anonymous$$athf.Acos(angle) * $$anonymous$$athf.Rad2Deg;
if (degree >= -fieldVision || degree <= fieldVision) {
for (int i = -45; i <= 45; i += 5) {
Quaternion rotation = Quaternion.AngleAxis(i, transform.up);
Vector3 ray = rotation * transform.forward;
Debug.DrawLine(transform.position, transform.position + ray * 30, Color.red);
if (Physics.Raycast(transform.position, ray, out hit, 30)) {
float vectorDistance = Vector3.Sqr$$anonymous$$agnitude(hit.point - transform.position);
if (vectorDistance > magnitude) { // find angle at which the distance was furtherest
magnitude = vectorDistance;
angle = i;
}
}
}
transform.Rotate(0f, angle, 0f);
}
}
transform.position += transform.forward * speed * Time.deltaTime;
}
Answer by sindrijo · Jun 30, 2016 at 02:32 PM
There are many different ways you could achieve this but I would probably go for some kind of collision hierarchy.
For example first do a Physics.SphereCast to check if there is anything at all in front of it. Then use an inactive camera to simulate the field of view (so it doesn't render) then you can use GeometryUtilities class to test visibility.
private bool IsSeenByThis()
{
Bounds playerBounds = new Bounds(); // Get this from the raycast results you can get this off a collider for example, or a trigger collison
var seeingRange = 10f;
var seeingAngle = 60f;
var camera = gameObject.AddComponent<Camera>();
camera.farClipPlane = seeingRange;
camera.fieldOfView = seeingAngle;
camera.nearClipPlane = 0;
camera.enabled = false; // We don't need to render anything.
var frustrumPlanes = GeometryUtility.CalculateFrustumPlanes(camera);
return GeometryUtility.TestPlanesAABB(frustrumPlanes, playerBounds);
}
You don't actually need the camera, you can generate the bounds yourself, it's really just 6 planes you need to define.
Answer by tejasachar · May 01, 2018 at 06:18 PM
Hey SuperRaed, i'm doing the exact same thing as you, Is it possible if at you could share with me the source. I would really like to learn.
Answer by LAKSHAYMAVIA · Oct 12, 2018 at 07:51 AM
You can acomplish this viewAngle is just some angle eg 70;
bool findThePlayer()
{
if (Vector3.Distance(transform.position, playerPos.position) < viewDistance)
{
Vector3 directionToPlayer = (playerPos.position - transform.position).normalized;
float angleBetweenGuardAndPlayer = Vector3.Angle(transform.forward, directionToPlayer);
if (angleBetweenGuardAndPlayer < viewAngle / 2)
{
Debug.Log("viewAngle " + viewAngle);
if (!Physics.Linecast(transform.position, playerPos.position, obstacle))
{
return true;
}
}
}
return false;
}
Your answer
Follow this Question
Related Questions
how do I add abilities(Scripts/GameObjects) to my path finding agent 1 Answer
AI question, characters escaping from light 0 Answers
Raycast on an AI Game object 1 Answer
Problem with AI and pathfinding. 2 Answers
Raycast pathfinder nodes 1 Answer