2
\$\begingroup\$

I am trying to figure out in my current game whether a gameObject is lit by a directional light or not. Below is my image inside the Unity game engine

enter image description here

As my game runs around a Day/Night cycle, I need to constantly check which hex tiles are lit and which are not. I am using one directional light source in my scene and I am rotating it around the x-axis for the day night cycle.

Currently, I am using the dot product to calculate if the tile is lit by the directional light but its not very accurate.

 Vector3 forward = Light.transform.TransformDirection(Vector3.forward);
 float dot = Vector3.Dot(forward, -(tile.transform.position - Light.transform.position));

Is there a better way to do check this inside Unity??

\$\endgroup\$
  • \$\begingroup\$ Dot is the way to do it if you want to find if it's facing the light. However, to know if it is lit by the light, you also need to test if it is occluded from the light source. Is this what you are asking how to do? \$\endgroup\$ – BWG Oct 19 '14 at 1:25
  • \$\begingroup\$ If that IS what you are asking I think you pretty much have to use shadow mapping. Fortunately your setup will work beautifully with a simple shadow map, but I don't know how to do it in Unity. \$\endgroup\$ – BWG Oct 19 '14 at 1:36
  • \$\begingroup\$ Shadow Mapping? I am not aware what that is but I will do more research on the same to see if that could work. Thanks a lot! \$\endgroup\$ – ckzilla Oct 19 '14 at 18:59
2
\$\begingroup\$

If you have the normal vector for the "top" face of the hex and the vector for the directional light it should be easy to determine if that hex is facing the light.

Note that this will check if the hex and the light are facing each other. This will not detect of another object is in between casting a shadow over the hex.

Vector3 lightDirection = directonLight.transform.forward;

Vector3 hexNormal = hex.transform.up;

//assumes normalized vectors
if (Vector3.Dot(lightDirection, hexNormal ) < 0) {
    //These vectors form an angle >90 and <270 degrees.
    //This means that the light is shining on this face
}
else {
    //these vectors form an angle either <=90 or >=270 degrees. 
    //This means that the light is not shining on this face.
}

If for some reason you are unable to determine the hex's orientation using one of the transform's axes, you could calculate it by comparing the hex's position with the center of the planet.

Vector3 hexNormal = (hex.transform.position - planetCenter.transform.position).normalized;
\$\endgroup\$
1
\$\begingroup\$

Interesting case. One way I can think of solving this would be to have an up normal on each hex tile. You would dot each hex's normal with the light source direction vector, and if the angle between them is more than 90 degrees you ignore all light calculations for the whole hex tile.

\$\endgroup\$
  • \$\begingroup\$ But to get the normal inside Unity, I would have to Raycast each tile, wouldn't I? And that would be an expensive calculation. However if I can figure out a way to not do it on every update, it could still work. I will definitely try it out. \$\endgroup\$ – ckzilla Oct 19 '14 at 18:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.