Best way of designing a building with independent window lighting

Hi,

I’m pretty new to Unity (professional software dev with 15+ years experience, trying some new stuff as a passionate hobbyist), and for the last couple weeks I tinkered with Unity. I’ve build some maps, played with the editor, saw some progress - all the exciting stuff you experience when trying new things. :slight_smile:

Now, I thought about building a story driven game with a low-poly open world environment, day-night cycle and some bells and whistles over the next three years.

The map should have 1000x1000 units. The house in the attached screenshot is roughly 25x25x25 units. I already worked on a prototype map before and experienced some issues, mainly about the correct light. That’s why I stepped back a little bit and made a simple scene to try everything out again.

I’ve attached a screenshot. The asset pack has an atlas for the buildings, and I would like the windows to be lit at night, so I created an emissive mask (which is black, and only has a white spot where the color for the windows is).

The downside is that all windows are lit. If you look outside your window (and if you have some houses around you at night), you will notice that there is barely a house which has all lights on.

Because I’m a dev, I’d like to write a script I can attach to a building, provide it the current game time and let the “house” decide, which lights to turn on and off.

From a 3d artist perspective - how would I need to modify the given asset? What would be the best and easiest way? I could think of two options:

  1. Make a texture for every building, where each window is mapped to it’s own “window” on the texture. I could then create different emissive maps.
  2. Remove all Windows from the model file itself, and create several windows as single prefabs which have their own emissive material. They could then be added to the bare model.

I’m not sure in terms of performance, though, and that’s one of the reasons I’d like to ask the more experienced users what they would do in my position. I guess at the end, there will be round about 50 buildings in the map. :slight_smile:

Providing all texture combinations for lights on or of per model does not seem like a good idea.
I would cut the windows into a separate mesh and let your script swap the material on them.
It should work without smashing the performance.
Another approach would be to handle everything inside the one shader for the model but that seems to complicated to bring a real benefit.

1 Like

Hi Malzbier! :slight_smile:

Haven’t thought about that, cool! I have barely any experience with Blender, so I refused to think in that way. But I tried it, and it seems to work pretty good. I can even use the default atlas, because the uv mapping is still working. I still need to come up with a valid “light” texture, though, but that should be manageable.

Now that I first tried the Blender approach, I wouldn’t want to try messing with shaders I guess. Although it would be interesting to know how it could be achieved what I want using shaders.

I think it might be valid to post a follow up. I’ve created a small Video which demonstrates what I’ve achieved so far:

Basically I did what fffMalzbier suggested (thanks again!) and moved every window in a separate mesh with Blender, which was pretty easy to do.
I then wrote a small script, which will change the material randomly every 5 seconds. It finds the right meshes by a tag called “Window”:

using UnityEngine;
using System.Collections;
using System;
using System.Collections.Generic;

public class HouseLightsController : MonoBehaviour {

    private List<MeshRenderer> _allWindowsMeshRenderers;
    private System.Random _random;

    public Material DarkWindowMaterial;
    public Material LightWindowMaterial;

    // Use this for initialization
    void Start () {
        _allWindowsMeshRenderers = LoadAllWindowsMeshRenderers();
        _random = new System.Random();
        InvokeRepeating("ChangeWindowLights", 2, 5F);
    }

    private List<MeshRenderer> LoadAllWindowsMeshRenderers()
    {
        var allWindowsObjects = this.GetComponentsInChildren<MeshRenderer>();
        var allWindowsMeshRenderers = new List<MeshRenderer>();

        foreach (MeshRenderer obj in allWindowsObjects)
        {
            if (obj.tag == "Window")
                allWindowsMeshRenderers.Add(obj);
        }
  
        return allWindowsMeshRenderers;
    }

    private void ChangeWindowLights()
    {
        for (int i = 0; i < _allWindowsMeshRenderers.Count; i++)
        {
            int result = UnityEngine.Random.Range(0, 2);
            _allWindowsMeshRenderers[i].material = result == 1 ? LightWindowMaterial : DarkWindowMaterial;
            DynamicGI.UpdateMaterials(_allWindowsMeshRenderers[i]);
        }
    }

}

Now, the next step might be to a) edit all 50+ models (Yay!) and b) to write a shader, so I could add a transition between the two materials. This could add some more realism, although I don’t know if this is doable at all.

Finally, you might notice some spots that shouldn’t be lit. If I would make an educated guess, I think it has to do with wrong lightmaps for the model, right?

1 Like