How can I achieve this particular 2D lighting effect?

Hi all, I am currently working on a 2D game but have ran into an issue with lighting.
Here is a screenshot of the game:

alt text

As you can see, the character has a point light around him. However, I would like to achieve this effect (edited above image to show what I mean):

alt text

The wall, as highlighted in the image, should be blocking the light.
Can anyone help with this?

The short answer: You’ll need to add some form of depth using box colliders and “popping out” that wall so it’s at the very least above the depth your light is at.

Why?
Unity is a 3D engine. 2D lights don’t exist. Think of using 2D in Unity as drawing a wall on a sheet of paper, and then shining a torch at it. As we all know, the wall won’t block the light. So, instead, we need to “pull out” that wall - like placing a block on top of your paper and paint the wall on top of it. This can simply be done by a box collider and move your wall sprite forward. A little like this (viewed in 3D for simplicity):

34985-2d-wall.png

That’s not quite a full solution however! From the looks of it, your character probably heads down towards the bottom of the wall, i.e. this region here:

34982-wall-bottom.png

When this happens, you’ll probably want that wall to light up. The simple solution is change the depth of your wall by script. In effect, when your player is down at the bottom of the screen, the wall is flat against the background. Then you can introduce full shadows etc to get some nice lighting effects (if you’re after that of course!).

Changing the depth of your wall

To prevent any confusion, “top” and “bottom” refer to the vertical positions on the screen!

Your player probably moves vertically on the screen via the Y axis in 3D space. This means that there will be a particular Y value that the player will be at when their at the top of the screen, and another Y value that they will be at when their at the bottom of the screen, or more specifically, at the bottom part of that wall. These values can be easily found based on the dimensions and position of your wall as a separate object.

So, after separating out your wall as described above, add a script to the wall. This script needs to be able to access your player GameObject, so make sure it has a reference available to that. In that script, do something along these lines (rough C#):

float MinDepth=1f;
// This limits how far "out" of the screen the wall can pop. Max is DepthRange+MinDepth.
float DepthRange=9f;
float WallHeight;
float WallBottom;

void Start(){
    // Get the "vertical height" (on the screen) of the wall - assumes a scaled quad with your image on it
    WallHeight=transform.localScale.y;

    // Find the "bottom" of the wall first. That's the Y coordinate of the very bottom edge of the wall. The walls transform point is in the middle of the wall, so that's why we take half of it's height to get to the bottom.
    WallBottom=transform.position.y - WallHeight/2f;    
    

}

void Update(){
    
    // Get the players Y position - that's their vertical position on the screen:
    float playerY=ThePlayerGameObject.transform.position.y;
    
    // Next, a simple interpolation. How far "up" the wall the player is as a percentage:
    float relativePosition=(playerY-WallBottom)/WallHeight;
    
    // Clip it:
    if(relativePosition<0f){
       // Beyond the bottom of the wall (right at the bottom of the screen)
       relativePosition=0f;
    }else if(relativePosition>1f){
        // Beyond the top of the wall (not possible in your image, but provided for clarity anyway)
        relativePosition=1f;
    }

    // Map it to our depth values and apply:
    transform.position.z=(relativePosition * DepthRange) + MinDepth;
    
}

This will result in no visual effects to the player. The lighting however reacts correctly - as the player approaches the bottom tip of the wall, it starts gracefully fading in. Make sure you watch what’s going on in the scene view to get the best idea of what this script actually does!

I have no experience with 2d programming, but in theory, couldn’t you just have everything in the game world (characters, terrain, items etc) in the lowest layer, then put the lighting effect in the layer above that (or, if the effect isn’t scripted, just the black image with the hole in the middle), and in the layer above that have black areas where the walls or anything else that blocks light are. Taht way, the black wall areas would always be visible.