- Home /
Simulated Sun Position
Hi All
I'm having some trouble finding an answer to this, there are a lot of similar questions, but none that quite match what I'm after, I'll do my best to explain what I'm after (I'm kinda rubbish at explaining things).
I have a directional light which is my sun, and that works well for what I'm after in regards to lighting, and I want it to move across the sky as time progresses.
Now I have tried the following bits of code:
transform.Rotate(0.1f, 0, 0);
and
xRotation += 0.1f;
transform.eulerAngles = new Vector3(xRotation, 0, 0);
The first one works alright to an extent, but what I'm specifically after is to be able to set the absolute angle (hence setting the Euler Angles), but the problem arises when I want the sun to appear higher, or lower over the horizon e.g for it being winter the sun would be lower down in the sky, and summer it would be higher in the sky.
Basically I want to be able to say at any point the sun is 20deg, 36deg etc. (or 0.055f, 0.1f) above the horizon, and then being able to say the same thing about it's angle in the sky.
I hope I have explained what I'm after, I'm relatively new to Unity, but have been programming for about 10 or more years, and haven't had much experience with 3D stuff before...
Answer by ThibaultUrien · Dec 07, 2018 at 10:18 AM
I'm not sure why are you not okay with what you are currently doing. I've myself toyed a bit with this question of placing the sun so I'll just tell you what I'm doing:
In the astronomic field, the parameters used to describe the position of the sun from an observer on the ground are usual the azimuth and the elevation angle (or zenithal angle, which is 90° - elevation angle).
The elevation angle tell you how high the sun is, so it's seem that it's what you want to control. The elevation angle is always between 0° and 90°, 0° when the sun is at the horizon and at 90° when right above. The azimuth is the angle the sun make with the northern direction, it's value are usually between 0° and 360°. So around midday in north hemisphere, the sun is on the south so it's azimuth is at 180°.
Those two astronomical angles can be directly seen as Euler angle of your light in unity:
Usually in unity game y axis is vertical, if that's your case use the y Euler angle to set the azimuth.
To set the elevation angle, you need to know what direction you want to be East. On my project, I was using the +Z direction as North, so my East direction was +X. If your cardinal points are supposed to be on world axis, use the Euler angle of the axis matching your East.
I assume in your case you can set the elevation angle by setting the X Euler angle because you also have the north/south axis on the z axis.
That would give you the following implementation :
transform.eulerAngles = new Vector3(elevation, azimuth, 0);
If your cardinal point are not aligned with your world referential, and that for some reason you need to have east to be in arbitrary direction (idk, let say (1.4142,0,1.4142) ), put your light in an empty parent game game object and rotate this object so that either the X or Z axis of your light are pointing north. Then modify the Euler angle of the localRoation of your light to set the elevationAngle you want. If that so the implementation would be somting like that :
transform.localEulerAngles = new Vector3(elevation, azimuth, 0);
If you want to be able to compute those angle depending on the time of the day and the position of the observer on the Earth you can check this repo that do it in js. Note that it may be to complex and precise for most game designe purpose that don't actually require the actual angle.
If you don't care about the excatitude of the value of the angle, you can put your light in a empty parent game object, then change the x and y Euler angle of this parent object to set the midday position of your sun. Then change the y value of the localRotation of you sun to make it move around the day. If you setup things like that, you can just do :
//I don't know how you keep track of time, return 0f just after midnight, 0.5f for midday and 1f just beformidnight
var fractionOfDay = GetFractionOfDay();
transform.localEulerAngles = new Vector3(0, (fractionOfDay - 0.5)*360, 0);