A Little Bit of Jank goes a Long Way! (Patreon)
Content
My next major milestone is going to be v0.3, which is going to be the first time A Very Full House is an actual game instead of just a couple of cute demos. That means it needs mechanics, and one of the core ones is having the time of day change after you take an action.
A couple of days ago I started in on that process, and I was immediately presented with the question of how to handle the art for different lighting environments. I considered doing time-specific art (both for the background and all of the characters), but that would take a lot of time and be really inflexible if I want to change something in the future. It would also be difficult to have you move between indoor and outdoor scenes. Instead I decided to play to my strengths and use Unity to handle all of the live lighting.
First, I had to move the whole project to Unity's Universal Rendering Pipeline (URP for short). Unity has native 2D lighting support if you're using URP, and most of the changeover was painless. I had to rewrite the outline shader used for highlighting objects to work properly with the new shader pipeline, but that ended up being fairly easy. (side note: if you want a simple outline shader graph that work well with soft-edged sprites let me know!)
So I had working lights, but there was a problem: lights on the token map (the part of the game you walk around on) showed up on your character portrait. Not having the portrait be dynamically lit would have been the easy solution, but it wasn't the fun one. So instead of calling it good enough embarked on a project to have the portrait be lit with the same effects as the character token, without the two overlapping. Thus began the jank.
Unity doesn't have a simple way to collect lighting information at an arbitrary point (light probes exist for 3d lighting, but they're for a fixed spot and fairly low resolution. Not ideal for this purpose), so I had to figure one out for myself. After thinking about it I realized there is a simple way to get the lighting information at a spot: Put a sprite down and see what colour it ends up. Lighting information for a sprite is calculated at render time, so I would need a camera to look at that sprite, and then I could check what colour the pixels were. Adding extra cameras to a scene is normally a big performance hit, but I could make the view size for each camera tiny, only have our test sprites on their render layer, and have them render to a tiny texture (in theory a 1x1 would work. I got some errors with that, so they're 16x16). In theory this should drastically limit their performance impact.
So that's what I did. Each character now has a small grey square (white doesn't pick up saturated colours correctly, because white is already 100% saturated!) on an invisible layer, which is viewed by a camera that only sees that grey square. The colour it sees is passed to an area light on the character portrait. The result is a character portrait that has dynamically updating lighting as you walk around! Performance didn't take much of an impact, so I'm happy.
Is it still janky if it works?