Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Fix lag for field of view shadow generation.

Discussion in '2D' started by fr0gi, Oct 2, 2022.

  1. fr0gi

    fr0gi

    Joined:
    Feb 19, 2022
    Posts:
    3
    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.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEditor;
    5.  
    6. public class fieldofview : MonoBehaviour {
    7.  
    8.     public LayerMask targetMask;
    9.     public float radius;
    10.     public int NumberOfRays;
    11.  
    12.     private Vector2 LastStart;
    13.     private Vector2 LastEnd;
    14.     private bool Last;
    15.  
    16.     public GameObject MeshHolder;
    17.     public GameObject Mesh;
    18.  
    19.     public void Start(){
    20.         for (int i = 0; i < NumberOfRays; i++){
    21.             GameObject shadow = Instantiate(Mesh, new Vector2(0, 0), Quaternion.identity);
    22.             shadow.transform.SetParent(MeshHolder.transform);
    23.         }
    24.     }
    25.  
    26.     void Update(){
    27.         for (int i = 0; i < NumberOfRays; i++){
    28.             Mesh mesh = MeshHolder.transform.GetChild(i).GetComponent<MeshFilter>().mesh;
    29.             Vector3[] vertices = mesh.vertices;
    30.             Vector3[] normals = mesh.normals;
    31.             MeshHolder.transform.GetChild(i).gameObject.SetActive(true);
    32.  
    33.             var dir = Quaternion.Euler(0, 0, i * 360/NumberOfRays) * transform.right;
    34.             Vector3 startPosition = transform.position;
    35.             Vector3 endPosition = dir * radius + transform.position;
    36.  
    37.             RaycastHit2D hit = Physics2D.Linecast(startPosition, endPosition, targetMask);
    38.  
    39.             if(hit.collider != null){
    40.                 if(Last){
    41.                     Vector3[] setvertices = new Vector3[4]{
    42.                         new Vector2(LastStart.x, LastStart.y),
    43.                         new Vector2(LastEnd.x, LastEnd.y),
    44.                         new Vector2(hit.point.x, hit.point.y),
    45.                         new Vector2(endPosition.x, endPosition.y)
    46.                     };
    47.                     mesh.vertices = setvertices;
    48.                     mesh.RecalculateBounds();
    49.                 }else MeshHolder.transform.GetChild(i).gameObject.SetActive(false);
    50.                 LastStart = hit.point;
    51.                 LastEnd = endPosition;
    52.                 Last = true;
    53.  
    54.                 Debug.DrawLine(hit.point, endPosition, Color.green);
    55.             }else {
    56.                 Last = false;
    57.                 MeshHolder.transform.GetChild(i).gameObject.SetActive(false);
    58.             }
    59.         }
    60.     }
    61. }

    Output-
    upload_2022-10-1_22-49-30.png

    I am have a problem of
     
    Last edited: Oct 2, 2022
  2. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,620
    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.

    Code (CSharp):
    1. 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<T>" 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:



     
  3. fr0gi

    fr0gi

    Joined:
    Feb 19, 2022
    Posts:
    3
    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.
     
  4. fr0gi

    fr0gi

    Joined:
    Feb 19, 2022
    Posts:
    3
    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
    upload_2022-10-2_13-19-15.png
    What I want to do
    upload_2022-10-2_13-19-29.png
     
  5. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,620
    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.