Unity 2D: Visualise a field of view cone

Good Afternoon, I’m trying to implement a field of view cone for my enemy where if the player enters this cone the enemy will chase them. I have worked out the logic for the enemy regarding the player detection. Now I need to visualise the cone in the gameview to show the user the area they will be spotted. An important feature of this cone is that it wont pass through objects with the layer tag “obstacle” this way the player has hiding spots.

The Image below demonstates how I have used raycasts to show the side boundaries of the view cone and also to the vertices of the object from the enemy (this probably isn’t ideal since my object might have many vertices and at the moment I need to input the vertex positions manually in the inspector which is tedious). I believe all I need to do is “fill in” the gaps between the raycasts but im unsure how easy this is to do.

Here is the mentioned image (The “G” shape is an obstacle):

And here is the code I have so far:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class EnemyFOV : MonoBehaviour
{

    [SerializeField] private List<Vector3> obstacleVertices; // a list of all the obstabcle vertices in the level
    [SerializeField] private List<Vector3> obstacleVerticesInRange = new List<Vector3>(); // a list of the obstacle vertices that will be within the enemy's FOV
    [SerializeField] private float enemyViewDistance; // the max distance the enemy can see
    [SerializeField] [Range(0, Mathf.PI)] private float enemyViewAngle; // the angle above and below the horizontal axis the enemy can see
    [SerializeField] private LayerMask hitLayers; // the layers the enemy can't see through
    [SerializeField] private RaycastHit2D boundLineTop;  // the top bounding line of the cone
    [SerializeField] private RaycastHit2D boundLineBottom; // the bottom bounding line of the cone

    // Update is called once per frame
    void Update()
    {
        bool movingRight = GetComponent<EnemyMovement>().movingRight; // get which way the enemy is facing so we know where to search for obstacle vertices
        int sign = 0;
        // get a list off all the obstical vertices in the enemy's FOV
        obstacleVerticesInRange = new List<Vector3>(); // clear the list of vertices in range
        for (int vertexIndex = 0; vertexIndex < obstacleVertices.Count; vertexIndex++) // for each element of the list
        {
            // find the angle between the two positions
            Vector2 direction = new Vector2(obstacleVertices[vertexIndex].x - transform.position.x, obstacleVertices[vertexIndex].y - transform.position.y);
            if (obstacleVertices[vertexIndex].y > transform.position.y)
            {
                sign = 1;
            }
            else
            {
                sign = -1;
            }
            float angle = Vector2.Angle(Vector2.right, direction) * sign * (Mathf.PI / 180);

            if (Vector3.Distance(obstacleVertices[vertexIndex], transform.position) <= enemyViewDistance && ((movingRight && Mathf.Abs(angle) <= enemyViewAngle) || (!movingRight && Mathf.Abs(Mathf.PI - angle) <= enemyViewAngle))) 
            {
                obstacleVerticesInRange.Add(obstacleVertices[vertexIndex]); // add the object to the List
                // Send a raycast from the enemy to the vertex
                Vector3 origin = transform.position;
                RaycastHit2D sightLine = Physics2D.Raycast(origin, direction, enemyViewDistance, hitLayers); // creates a raycast from the enemy in the direction of the obstacle vertex colliding only with the listed layers
                //TODO chuck out a ray at the angles of view of enemy
                // simulate the raycast (for demonstration purposes)
                if (sightLine.collider) // if the ray has hit an obsticle 
                {
                    UnityEngine.Debug.DrawLine(new Vector2(transform.position.x, transform.position.y), sightLine.point, Color.red); // if a collider is hit draw from enemy to collision point
                }
                else
                {
                    UnityEngine.Debug.DrawLine(new Vector2(transform.position.x, transform.position.y), new Vector2(transform.position.x, transform.position.y) + direction * enemyViewDistance, Color.white);
                }
            }

            // also send the rays of the sides of the FOV cone
            Vector2 pointOnTopLine;
            Vector2 pointOnBottomLine;
            if (movingRight)
            {
                pointOnTopLine.x = enemyViewDistance * Mathf.Cos(enemyViewAngle) + transform.position.x;
                pointOnTopLine.y = enemyViewDistance * Mathf.Sin(enemyViewAngle) + transform.position.y;
                pointOnBottomLine.x = enemyViewDistance * Mathf.Cos(enemyViewAngle) + transform.position.x;
                pointOnBottomLine.y = enemyViewDistance * -Mathf.Sin(enemyViewAngle) + transform.position.y;
            }
            else
            {
                pointOnTopLine.x = enemyViewDistance * Mathf.Cos(Mathf.PI - enemyViewAngle) + transform.position.x;
                pointOnTopLine.y = enemyViewDistance * Mathf.Sin(Mathf.PI - enemyViewAngle) + transform.position.y;
                pointOnBottomLine.x = enemyViewDistance * Mathf.Cos(Mathf.PI - enemyViewAngle) + transform.position.x;
                pointOnBottomLine.y = enemyViewDistance * -Mathf.Sin(Mathf.PI - enemyViewAngle) + transform.position.y;
            }

            // visualise the boundaries
            UnityEngine.Debug.DrawLine(new Vector2(transform.position.x, transform.position.y), pointOnTopLine, Color.yellow);
            UnityEngine.Debug.DrawLine(new Vector2(transform.position.x, transform.position.y), pointOnBottomLine, Color.yellow);
        }
    }
}

I should mention I’m new to Unity and coding so thank you for your patience!

Sebastian Lague did it in 3d - but really it could be considered 2d since it was top down…

He creates a dynamic mesh on the fly.

Hopefully that’s what you’re talking about.

There is a better (and much more performant way to do this, using Vector calculus. https://gamedev.net/tutorials/programming/math-and-physics/vector-maths-for-game-dev-beginners-r5442/ check out this article and read about dot product, I am making a stealth game (in 3d) right now, and I’ve used this method and it’s worked great

Why not use a 2D lighting solution from the asset store? this one is free… Hard Light 2D | Particles/Effects | Unity Asset Store

OR to build it yourself… I think you’d need to iterate through all of your scene objects/blocks finding near and far corners, then projecting them in 2D onto a virtual plane or a circle represented in a list of run-length data… the list would be a list of pretty much 2 states… I can see clearly to the max distance ( to the plane), or it is blocked by an object… then you enter in sorted z-co-ordinate / ranges into the list, sorted by view angle from top to bottom of the view arc.
This would also work for objects ‘shadowed’/hidden by other objects… you wouldn’t enter those values in the list as they are hidden but other items already in the list that are closer. You need to do some vector 2d math here… especially for partially hidden line segments. Or you could actually draw into it like a z-buffer.

Then to re-render it… you’d walk the list, from tip to bottom… building and rendering triangles like a fan. You could either render shadows, or light… view cones, or blocked view areas…