Search Unity

Light in 2D Game

Discussion in '2D' started by Tempest74, Aug 28, 2017.

  1. Tempest74

    Tempest74

    Joined:
    May 17, 2017
    Posts:
    133
    Do you know any good tutorial about light in 2D game?
     
    Last edited: Aug 28, 2017
  2. AbgaryanFX

    AbgaryanFX

    Joined:
    Jan 9, 2010
    Posts:
    167
  3. radonthetyrant

    radonthetyrant

    Joined:
    Feb 14, 2014
    Posts:
    6
    Why not use the Standard shader with the standard lighting?
     
  4. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,807
  5. blanktarget

    blanktarget

    Joined:
    Aug 28, 2017
    Posts:
    20
    The example from Jeff is great. Coding that from scratch is way beyond me!
     
  6. Deleted User

    Deleted User

    Guest

    Well for a start here's a script that will draw lines around a circle from a single point, turn those lines into raycasts and detect their hit locations and you're on your way.
    Code (csharp):
    1.  
    2. public class circle : MonoBehaviour {
    3.  
    4.     private Vector2 _origin;
    5.     private Vector2 _circumfrance;
    6.     public float radius = 8;  //size of the circle, if using rays this becomes arbitrary
    7.     public float lines = 360; // how many lines make up our full circle
    8.     private int linenumber;
    9.     private float _degrees;
    10.  
    11.     public float interval = .5f; //Setting this to 0 will draw a line every frame, if you want to draw rays you may want to loop through them all in a single frame
    12.     private float timer;
    13.  
    14.     public Material spriteMaterial; //set this to sprite material
    15.  
    16.     // Use this for initialization
    17.     void Start () {
    18.         _origin = transform.position;
    19.         _degrees = 360 / lines;
    20.         linenumber = 1;
    21.         timer = Time.time - interval;
    22.     }
    23.  
    24.     // Update is called once per frame
    25.     void Update () {
    26.         if (Time.time > timer + interval && linenumber <= lines) //after a delay draw the next segment
    27.         {
    28.             float t_x = _origin.x + radius * Mathf.Sin((_degrees * linenumber) * Mathf.PI / 180);
    29.             float t_y = _origin.y + radius * Mathf.Cos((_degrees * linenumber) * Mathf.PI / 180);
    30.             _circumfrance = new Vector2(t_x, t_y);
    31.             Debug.Log(_circumfrance.ToString());
    32.             DrawLine(_origin, _circumfrance, Color.red);
    33.             linenumber++;
    34.             timer = Time.time;
    35.         }
    36.     }
    37. //this is for creating a line
    38.     void DrawLine(Vector2 startingPoint, Vector2 endPoint, Color color)
    39.     {
    40.         GameObject obj = new GameObject();
    41.         obj.name = "Line " + linenumber;
    42.         LineRenderer line = obj.AddComponent<LineRenderer>();
    43.         line.material = spriteMaterial;
    44.         line.enabled = true;
    45.         line.sortingLayerName = "UI";
    46.         line.sortingOrder = 2;
    47.         line.positionCount = 2;
    48.         line.SetPosition(0, startingPoint);
    49.         line.SetPosition(1, endPoint);
    50.         line.startWidth = .1f;
    51.         line.endWidth = .1f;
    52.         line.useWorldSpace = true;
    53.         line.startColor = color;
    54.         line.endColor = color;
    55.     }
    56. }
    57.  
    edit: someone posted this in answers, hope it helps http://unitycoder.com/blog/2012/02/15/raycast-realtime-visibility-2-0/
     
    Last edited by a moderator: Aug 29, 2017
    Deleted User likes this.
  7. swaglordxxx

    swaglordxxx

    Joined:
    Dec 13, 2016
    Posts:
    6
    What specifically about light do you need to know? How to make your own lighting model? How to add light to a 2D scene?
     
  8. Tempest74

    Tempest74

    Joined:
    May 17, 2017
    Posts:
    133
    I wanted to know how to use light in 2d scene. I found that after a lot of search
     
  9. Deleted User

    Deleted User

    Guest

    You just need to create a diffuse sprite material and attach it to your sprites and simple lights will work.
     
  10. Deleted User

    Deleted User

    Guest

    ok, i got as far as casting rays in all directions and getting the jittery edges, I'm not sure how to go about finding the vertices of colliders, i guess he made them out of line segments with all the vertices defined whereas in unity you'd want it to be compatible with any configuration of colliders. I can get a hit on a polygon collider and convert its vertices into world space but I don't know where they are until I've hit them with a ray anyway and it can only get the vertices of polygon colliders. Neat idea though, if anyone has thought of a solution to this i'd love to know.
     
  11. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,807
    You can do an OverlapCircleNonAlloc physics check in the size of the light's radius to find all the colliders in range of the light, then raycast towards the verts.
     
    Deleted User likes this.
  12. Deleted User

    Deleted User

    Guest

    But wouldn't that still only work on polygon colliders? I could calculate the bounding box of box and edge colliders but what if I hit a circle collider?
     
  13. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,807
    Well one option is to use polygon colliders for all your shapes. That really wouldn't be so bad I think.

    However if it's a circle collider you can still calculate points to cast towards. You have the center and the radius, so you know where the outer-most sides are. You just need to use a direction perpendicular to the light-facing direction to get those outer points relative to the light source.
     
    Deleted User likes this.
  14. Deleted User

    Deleted User

    Guest

    That would do it, thanks, now the question is should i code it for the sake of coding it considering I really have no use for dynamic lighting in my current project? It would be neat but maybe i'll just hold off until i can think of a project that could use it.
     
  15. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,807
    Nothing wrong with doing something just to learn, or for the hell of it. You never know what you'll learn that can help you with solving other problems.
     
  16. Deleted User

    Deleted User

    Guest

    is there a more reliable
    Iway to see if a point is being blocked than the way i'm doing it?
    Code (csharp):
    1.  
    2.     void findVertices(Vector2 origin, float radius)
    3.     {
    4.         RaycastHit2D[] objs = new RaycastHit2D[360];
    5.         Physics2D.CircleCastNonAlloc(origin, radius, Vector2.zero, objs);
    6.         foreach (RaycastHit2D obj in objs)
    7.         {
    8.             if (obj)
    9.             {
    10.                 Vector2[] points = obj.transform.GetComponent<PolygonCollider2D>().points;
    11.                 for(int i = 0; i < points.Length ; i++)
    12.                 {
    13.                     points[i] = obj.transform.TransformPoint(points[i]);
    14.                     RaycastHit2D hit = Physics2D.Linecast(origin, points[i]);
    15.                     if (points[i] == hit.point)
    16.                     {
    17.                         Debug.DrawLine(origin, points[i], Color.red);
    18.                     }
    19.                 }
    20.             }
    21.         }
    22.     }
    23.  
    edit: I now realize this doesn't work because if the linecast to the side I see doesn't actually hit it'll return null
    without worrying about memory allocation for the moment i can kindof fudge it like this
    Code (csharp):
    1.  
    2.     void findVertices(Vector2 origin, float radius)
    3.     {
    4.         RaycastHit2D[] objs = Physics2D.CircleCastAll(origin, radius, Vector2.zero);
    5.         for (int h = 0; h < objs.Length; h++)
    6.         {
    7.             Vector2[] points = objs[h].transform.GetComponent<PolygonCollider2D>().points;
    8.             for (int i = 0; i < points.Length; i++)
    9.             {
    10.                 points[i] = objs[h].transform.TransformPoint(points[i]);
    11.                 RaycastHit2D[] hits = Physics2D.LinecastAll(origin, points[i]);
    12.                 if (hits.Length == 0 || hits[0].point == points[i])
    13.                 {
    14.                     Debug.DrawLine(origin, points[i], Color.red);
    15.                 }
    16.             }
    17.         }
    18.     }
    19.  
     
    Last edited by a moderator: Sep 7, 2017
  17. Deleted User

    Deleted User

    Guest

    Now i'm trying to create and use a sprite by overriding its geometry like so
    Code (csharp):
    1.  
    2.     void UpdatePolygon(GameObject polygon, Vector2[] v, UInt16[] triangles)
    3.     {
    4.         float hx = 0, hy = 0;
    5.         foreach (Vector2 vi in v)
    6.         {
    7.             if (vi.x > hx)
    8.                 hx = vi.x;
    9.             if (vi.y > hy)
    10.                 hy = vi.y;
    11.         }
    12.         float lx = hx, ly = hy;
    13.         foreach (Vector2 vi in v)
    14.         {
    15.             if (vi.x < lx)
    16.                 lx = vi.x;
    17.             if (vi.y < ly)
    18.                 ly = vi.y;
    19.         }
    20.         Vector2[] localv = new Vector2[v.Length];
    21.         for (int i = 0; i < v.Length; i++)
    22.         {
    23.             localv[i] = v[i] - new Vector2(lx, ly);
    24.         }
    25.         polygon.GetComponent<SpriteRenderer>().sprite.OverrideGeometry(localv, triangles);
    26.         polygon.transform.position = (Vector2)transform.InverseTransformPoint(transform.position) + new Vector2(lx, ly);
    27.     }
    28.  
    where I have an input such as
    and
    but i'm getting this where the yellow is the generated sprite
    :

    I feel like i forgot to multiply something by 3 but i can't think of what...
     
  18. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,807
    In that array of verts, you have many (0,0,0) entries in there, but all triangles share that one vert, so there should only be one entry for it at index 0.
     
    Deleted User likes this.
  19. Deleted User

    Deleted User

    Guest

    Oh, is that it? Facepalm
    And there we have it:
    I'm not going to post the code because its a mess and only works on polygon colliders atm but if anyone's attempting something similar I'd be happy to share.
    https://nkoeppel.itch.io/lighting-demo
     
    Last edited by a moderator: Sep 9, 2017
    LiterallyJeff likes this.