Fix lag for field of view shadow generation.

I have been working on creating a field of view script in unity. It is very inefficient and was thrown together without consideration for performance. I decided to make it, because using the regular shadow system was what I wanted, and each object required a script. There is also a problem with the shadows being jittery. Is there anything I can do to fix it, and if not, are there other good alternatives?

Script- Basically just casts a bunch of rays and creates meshes over them.

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

public class fieldofview : MonoBehaviour {

    public LayerMask targetMask;
    public float radius;
    public int NumberOfRays;

    private Vector2 LastStart;
    private Vector2 LastEnd;
    private bool Last;

    public GameObject MeshHolder;
    public GameObject Mesh;

    public void Start(){
        for (int i = 0; i < NumberOfRays; i++){
            GameObject shadow = Instantiate(Mesh, new Vector2(0, 0), Quaternion.identity);
            shadow.transform.SetParent(MeshHolder.transform);
        }
    }

    void Update(){
        for (int i = 0; i < NumberOfRays; i++){
            Mesh mesh = MeshHolder.transform.GetChild(i).GetComponent<MeshFilter>().mesh;
            Vector3[] vertices = mesh.vertices;
            Vector3[] normals = mesh.normals;
            MeshHolder.transform.GetChild(i).gameObject.SetActive(true);

            var dir = Quaternion.Euler(0, 0, i * 360/NumberOfRays) * transform.right;
            Vector3 startPosition = transform.position;
            Vector3 endPosition = dir * radius + transform.position;

            RaycastHit2D hit = Physics2D.Linecast(startPosition, endPosition, targetMask);

            if(hit.collider != null){
                if(Last){
                    Vector3[] setvertices = new Vector3[4]{
                        new Vector2(LastStart.x, LastStart.y),
                        new Vector2(LastEnd.x, LastEnd.y),
                        new Vector2(hit.point.x, hit.point.y),
                        new Vector2(endPosition.x, endPosition.y)
                    };
                    mesh.vertices = setvertices;
                    mesh.RecalculateBounds();
                }else MeshHolder.transform.GetChild(i).gameObject.SetActive(false);
                LastStart = hit.point;
                LastEnd = endPosition;
                Last = true;

                Debug.DrawLine(hit.point, endPosition, Color.green);
            }else {
                Last = false;
                MeshHolder.transform.GetChild(i).gameObject.SetActive(false);
            }
        }
    }
}

Output-
8483096--1128023--upload_2022-10-1_22-49-30.png
I am have a problem of

You didn’t say what was broken. How do you want it “fixed”? Do you mean how to make it more efficient?

Well…

If the shadows are based upon colliders then there’s no point doing this per-frame, physics doesn’t change per-frame unless you are doing that so update your shadows during the fixed-update and cache information until you know it has changed.

Collider2D[] rangeChecks = Physics2D.OverlapCircleAll(transform.position, radius, targetMask);

This gets the results as an array per-frame which you then leave to the GC to clear up so that’s wasteful. Never use the “All” or “NonAlloc” calls, only use the physics queries that don’t have a suffix. Use the ones that allow you to pass a “List” for results and reuse the list.

Lastly, to make something perform well, you have to only do what you absolutely must be doing i.e. the fastest code doesn’t run. You’re doing things like grabbing components, setting things active. I don’t follow your logic here but I’m sure it’s fine but logical doesn’t mean fast.

I’m not aware of 3rd party solutions on the Asset Store, perhaps there are but a new 2D shadow solution is just around the corner but maybe you cannot wait for that.

Here were some experiments from last year in terms of its interaction with physics:

https://www.youtube.com/watch?v=nPNg-_zgHOY

https://www.youtube.com/watch?v=tgr2NQsMFTE

https://www.youtube.com/watch?v=vc5PmF_D74w

Thank you MelevMay for pointing out the Collider2D check. I fixed the major lag by removing it (it was from some other testing and I forgot to take it out), but I still have some problems. To make the shadows look good, I have to set the rays to something like 1000. This obviously causes lag. Also, the shadows are also a bit jittery.

And instead of casting thousands of rays and lagging the game, how would I go about casting a ray to each closest edge?

what I am doing
8484029--1128179--upload_2022-10-2_13-19-15.png
What I want to do
8484029--1128182--upload_2022-10-2_13-19-29.png

A collider has 1 to n shapes. If you have a collider, you can retrieve its shapes using Collider2D.GetShapes(). Given a lists of PhysicsShape2D you can use the job-system to project a point to that shape.

There’s a lot for you to learn here though so be prepared to dig in.

Just don’t expect to brute-force this on the main-thread and expect good performance. Writing your own shadow system is a non-trivial task depending on how dynamic it is and how flexible you need to be with it.