So I am looking to build a game world like Prison Architect or RimWorld. I have played around with Unity’s based 2D lighting system however it does not seem to fill the needs I am looking for, the 2 biggest issues:
it seems that Unity’s lighting system was not built for top down games as I could not find a way to have a shadow caster only cast a shadow to a certain length to simulate height of tiles (for like a sun based shadow)
with the larger maps (like 500x500) it is possible to have hundreds of light sources and hundreds of shadow casters which did not perform great (and that was with nothing else happening)
My needs for shadows and lighting I think are actually relatively simple compare to what a lot of solution try to offer, those needs are:
be able to simulate a shadow based off of a sun
be able to simulate point lights that can be blocked by certain tiles (so a light does not go through a wall or something)
From what I have read and researched, it seems like the idea would be to generate shadow meshes based on tilemap data and then manipulate the vertices of those based based on the time of data to simulate a sun based shadow. Now I am sure I can figure out how to generate the mesh (I am doing similar thing already) and I can probably figure out how to manipulate the vertices too in the C# code however with there being 1000’s of shadows (like how each tree has a shadow in RimWorld) that would be moving ever so slightly all the time, doing that in the C# code (which I assume would be done on the CPU) would probably not going to fly. The problem I am going to have is figuring out how to off load that work to the GPU by using a vertex shader as I am having a pretty hard time find learning resources on that type of thing.
This one I am completely lost at. The big thing is that I want the point light to account for the structures around it (so the light on the other side is dimmer the more tiles that block it). I have no idea how to simulate lighting like this. I would guess something like that would be possible with fragment shaders (though I have not idea on where to even begin on that) but even if that was the case, I would even begin to guess on how that would be done.
A lot of this stuff seems to be related to shader work which seems to be one of the harder things to find resources for learning (and often that are complete unrelated as not sure how to apply those to this problem). Any advice, likes to resources, or whatever would be very helpful.
It looks like you’re already using Universal Rendering Pipeline (URP) and Unity’s 2D Lights?
You could look at the Shadow Caster 2D component’s source code and see if you can create your own component to generate shadows the same way, but with the set shape and length limitations you want.
This wouldn’t be any more expensive than using the Light 2D and shadow components already offered by the URP.
If you do this I’d love to see the script you come up with!
This is achieved using Light 2D of type Freeform, simply drawn to the shape you want for each wall.
By setting the Overlap Operation to Alpha Blend, it will multiply the Intensity by the Global Light on that pixel.
Assuming the scene has a Global Light intensity set to 1, and this Freeform light intensity set to 0.6, we end up with light for each pixel affected by the Freeform light being darker than the global light.
If you’re building your walls during runtime, perhaps you can figure out a script to modify the shape of the Freeform Light 2D when walls are created or modified. This means you’ll only need to set those lights up once until the wall is modified again.
@rarac
Yea, there seems to be a bit there however my needs to shadows / lighting are much simpler (relatively speaking I think).
@ZBerm
While I am using URP, I don’t intend to use any of Unity’s 2D lighting system. In my performance testing, it does not seem to handle my needs well as I can have a lot of lights and shadow casters at any point with a large zooming ability (which is needed), it does not natively support shadows that have a length to simulate height in a top down 2D game, and the fact that the lighting system not does seem to support lights wrapping around edges relatively well (my lighting needs are from the perspective of overlook everything as not from a single character).
It is also not just the elements that can cast shadows that can dynamically change at run time but the direction of the shadow itself need to change as the game will have a day / night cycle similar to RimWorld (the shadow will basically move in an arc from the bottom left in the morning → the bottom but a bit higher at noon → the bottom right in the evening). With fact that the shadows are going to be moving little by little all the time, I don’t think that updating the all the shadow casters each frame is going to be performant at all (again the zoom level possible will require a lot of updating per frame to be possible).
Considering I would have to modify / add to Unity 2D lighting system a bit anyways, I feel it would be better to at least try to build something custom anyways as Unity’s system has a lot of extra functionality (that leads to adding complexity and decreased performance) that can be avoid for my specific needs (I am not worried about building a 2D lighting system that can be used for a large number of game types).
I have been able to create a system for the sun shadow part for the time being. I end up creating a new mesh (1 for each chunk of the tilemap) for the right side or left side (depending on the time of day) and the bottom of any tile group that is considered a sun shadow caster. I then created a calculation based on a set of inputs that determines the placement of the vertices in order to generate the shape of the shadow based on a time value that is updated each frame. This gives me the effect needed. I also moved all of the calculations for the vertex movement into a vertex shader which always the C# code to only need to modify the shadow mesh when there are additions or removals of a tile that is a sun shadow caster tile which allows for a couple 100K shadow with virtually no performance hit (I start to see a 1 - 2 millisecond performance hit when I am in the 600K - 800K shadow count).
I have not worked on the lighting system part yet however based on my research, I have an idea about how I might be able to use a 2d grid based solution (along with a custom fragment shader) to give me similar results that I am looking for.
Hey @ryanzec thank you for sharing your top-down Tilemap shadow use cases here. This is a really interesting thread and I thought I’ll just chime in here. The 2D Graphics team is looking at improving the shadow interoperability with some of our core 2D feature areas and Tilemap is one of them.
You mentioned some good points of which I’ll be feedbacking them to the team. Let us know if you do encounter more use cases along the way or have some more feedback in general as these are super helpful!
The pergomance problem continues since 2019. When having a robust topdown tilemap with a few hundred Light2D the game’s performance goes down, making it impossible to create a large game using native light.
I was replying to this single-line post of yours but you didn’t state what hasn’t happened as it was immediately after a post indicating there’s a new system being worked on hence me posting some dev videos of that new system.
I’m not one the graphics engineers who worked on that new system however so there may be a setting to achieve that though. I presume you’ve used the new system and that it doesn’t give you what you desire?
Yes exactly. Could you pelase point me towards that setting which creates shadows as originally requested?
I also followed some instructions which for example have been suggested here:
These basically suggest, adjusting the shadow lengths by changing some of the provided ShadowRendering and associated scripts. However, the resulting shadows turned out to either be extremely ugly or at least nowhere close to what the actual result is supposed to be.
As I said above, I don’t know as I am not the developer for this. My reply was to clarify that a new shadow system was implemented and I asked if you had tried it. I am not familiar with the settings.
Ok so it seems like there is still no solution to this problem.
Could you please forward this feature request to have working 2D shadows from a top down perspective? Is there maybe a way to do this ourselves instead?