As the title says I want to know of a way to detect light levels at different points of a Unity Terrain that has dynamic lighting. A sun rises and sets, lights can be used… these all create light levels. I want to then spawn monsters outside of light levels that are too high. What I need is ideas how to find light level randomly in a big scene, so it has to be semi efficient. Any help or ideas are greatly appreciated.
Light level detection is a pretty complicated thing to do and many games implement it in different ways. In unity there are effectively three ways to do so. You can read more about it in this post Detect light/shadow falling on object? - Questions & Answers - Unity Discussions but i’ll try and give my best explanation of each.
First:
The first way is kind of faking light level detection. Basically if you have a point that you want to check what the light level at is then you can do a distance and raycast calculation to figure out what the lights power on that point is. The raycast detects any blocking objects and the distance can be used to calculate a falloff from the light source. This implementation can get slow very quickly though if you do the calculation with to many lights so it’s usually a good idea to have some mechanism that can cull out a large number of lights at once such as using trigger colliders to only consider lights within the relevant area.
Second:
If you want the true light level however you are going to have to work with the shadow map. The shadow map is a texture that holds a shadow on it for either the whole or part of the scene. You can read a lot more on it in the discussion I posted, but the general consensus is that it is far to slow as you have to do numerous calculations on the cpu. Its also not possible if you are doing defered rendering as dynamic shadow maps are never created.
Third:
The final, and probably best solution is to actually take advantage of rendering. As the post discussed you can use RenderTargets to get the amount of lighting on a piece of the screen. You can make this a bit more reliably by creating an orthogonal camera, placing it a little above the point you want to look at (enough so it doesn’t clip with the ground) and telling the camera to render to a small render target. You can make the render target very small as well because you don’t really care about a good looking image, just the average color (so a 32x32 would probably work very well). You can then take that render target, average the brightness and then you have your darkness to lightness level of that area. You can adjust the orthogonal size as well if you want to deal with larger or smaller patches.
Hope this helps you out.