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?

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.

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.

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.

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;
    }