Line of Sight using Mesh ,Line of Sight Mesh

I am making a Line of Sight (LOS) system using a mesh.

The mesh is partially working. It works in the sense that it detects collisions with the raycast.point however the raycast.point does not align with the actual mesh.

I’m at a bit of a loss as to what’s happening, as any changes I make makes it worse and/or breaks it.

Any help would be greatly appreciated!

[SerializeField] Rigidbody rb;
// Start is called before the first frame update
void Start()
{
    
}

// Update is called once per frame
void Update()
{
    Vector3 origin = Vector3.zero;
    Mesh mesh = new Mesh();
    GetComponent<MeshFilter>().mesh = mesh;

    float fov = 90f;

    int rayCount = 50;
    float angle = 0f;
    float angleIncrease = fov / rayCount;
    float viewDistance = 50f;

    Vector3[] vertices = new Vector3[rayCount + 1 + 1];
    Vector2[] uv = new Vector2[vertices.Length];
    int[] triangles = new int[rayCount * 3];

    vertices[0] = origin;

    int vertexIndex = 1;
    int triangleIndex = 0;

    for (int i = 0; i <= rayCount; i++)
    {
        Vector3 vertex = origin + GetVectorFromAngle(angle) * viewDistance;
        RaycastHit rayCastHit;
        Physics.Raycast(origin, GetVectorFromAngle(angle) * viewDistance, out rayCastHit);
        Debug.DrawRay(origin, GetVectorFromAngle(angle) * viewDistance, Color.blue);

        if (rayCastHit.collider == null)
        {
            Debug.Log("no hit");
            vertex =  origin + GetVectorFromAngle(angle)* viewDistance;
        }
        else
        {
            Debug.Log("hit");
            vertex = rayCastHit.point;
        }
        vertices[vertexIndex] = vertex;

        if (i > 0)
        {
            triangles[triangleIndex + 0] = 0;
            triangles[triangleIndex + 1] = vertexIndex - 1;
            triangles[triangleIndex + 2] = vertexIndex;

            triangleIndex += 3;
        }
        vertexIndex++;

        angle -= angleIncrease;
    }

    mesh.vertices = vertices;
    mesh.uv = uv;
    mesh.triangles = triangles;
}

public static Vector3 GetVectorFromAngle(float angle)
{
    float angleRad = angle * (Mathf.PI / 180f);
    return new Vector3(Mathf.Cos(angleRad), 0, Mathf.Sin(angleRad));
}

}

For me your code works as long as the gameobject with the script has position (0,0,0), scale (1,1,1) and rotation (0,0,0).

If you want it to work with any position, you need to keep in mind that Physics.Raycast works in world space while vertex positions are in local space (coordinates are relative to the gameobject).

I modified your code to allow moving it:

[SerializeField] Rigidbody rb;
// Start is called before the first frame update
void Start()
{

}
// Update is called once per frame
void Update()
{
    Vector3 origin = transform.position;//MODIFICATION: gameobject's position in world space
    Mesh mesh = new Mesh();
    GetComponent<MeshFilter>().mesh = mesh;
    float fov = 90f;
    int rayCount = 50;
    float angle = 0f;
    float angleIncrease = fov / rayCount;
    float viewDistance = 50f;
    Vector3[] vertices = new Vector3[rayCount + 1 + 1];
    Vector2[] uv = new Vector2[vertices.Length];
    int[] triangles = new int[rayCount * 3];

    vertices[0] = Vector3.zero;//MODIFICATION: this is in local space
    int vertexIndex = 1;
    int triangleIndex = 0;

    for (int i = 0; i <= rayCount; i++)
    {
        Vector3 vertex;//MODIFICATION
        RaycastHit rayCastHit;
        bool hit = Physics.Raycast(origin, GetVectorFromAngle(angle) * viewDistance, out rayCastHit);
        Debug.DrawRay(origin, GetVectorFromAngle(angle) * viewDistance, Color.blue);
        if (!hit)//MODIFICATION: recommended way to check if the raycast hit something
        {
            Debug.Log("no hit");
            vertex = GetVectorFromAngle(angle) * viewDistance;//MODIFICATION: local space, relative to this gameobject
        }
        else
        {
            Debug.Log("hit");
            vertex = rayCastHit.point - origin;//MODIFICATION: subtract origin to get into local space
        }
        vertices[vertexIndex] = vertex;

        if (i > 0)
        {
            triangles[triangleIndex + 0] = 0;
            triangles[triangleIndex + 1] = vertexIndex - 1;
            triangles[triangleIndex + 2] = vertexIndex;
            triangleIndex += 3;
        }
        vertexIndex++;

        angle -= angleIncrease;
    }
    mesh.vertices = vertices;
    mesh.uv = uv;
    mesh.triangles = triangles;
}
public static Vector3 GetVectorFromAngle(float angle)
{
    float angleRad = angle * (Mathf.PI / 180f);
    return new Vector3(Mathf.Cos(angleRad), 0, Mathf.Sin(angleRad));
}

If the gameobject has also rotation and/or scale, you can switch between world and local space using Transform.TransformPoint and Transform.InverseTransformPoint.

@RoopeKT, Thank you so much for the solution. I made a little change to make it fit for my game and want to share it for the people in need.

//2D modification: made it easy to change values during runtime to do some tests.
    [SerializeField] LayerMask layerMask;
    [Range(0,360)][SerializeField] private float fov = 90f;
    [SerializeField] private int rayCount = 50;
    [SerializeField] private float viewDistance = 50f;

    void Update()
    {
        Mesh mesh = new Mesh();
        GetComponent<MeshFilter>().mesh = mesh;

        Vector2 origin = transform.position;//2D Modification: changed to vector2
        Vector3[] vertices = new Vector3[rayCount + 1 + 1];
        Vector2[] uv = new Vector2[vertices.Length];
        int[] triangles = new int[rayCount * 3];

        float angle = 0f;
        float angleIncrease = fov / rayCount;
        int vertexIndex = 1;
        int triangleIndex = 0;
        vertices[0] = Vector3.zero;

        for (int i = 0; i <= rayCount; i++)
        {
            Vector3 vertex;
            //2D Modification: changed raycast to 2D version and gave it a layermask for detecting walls.
            RaycastHit2D hit = Physics2D.Raycast(origin, GetVectorFromAngle(angle), viewDistance, layerMask); 
            if (!hit)                                                                                         
            {
                vertex = GetVectorFromAngle(angle) * viewDistance;
            }
            else
            {
                vertex = hit.point - origin;
            }
            vertices[vertexIndex] = vertex;
            if (i > 0)
            {
                triangles[triangleIndex + 0] = 0;
                triangles[triangleIndex + 1] = vertexIndex - 1;
                triangles[triangleIndex + 2] = vertexIndex;
                triangleIndex += 3;
            }
            vertexIndex++;
            angle -= angleIncrease;
        }
        mesh.vertices = vertices;
        mesh.uv = uv;
        mesh.triangles = triangles;
    }
    public static Vector3 GetVectorFromAngle(float angle)
    {
        float angleRad = angle * (Mathf.PI / 180f);
        return new Vector3(Mathf.Cos(angleRad), Mathf.Sin(angleRad), 0); //2D Modification: placed Mathf.Sin to be on Y (not necessary, see below pictures for the difference).
    }

alt text

alt text