# Day and Night Cycle rotation Problem

Discussion in 'Scripting' started by PrieDayThor, Nov 12, 2015.

1. ### PrieDayThor

Joined:
Jun 18, 2015
Posts:
16
Hey guys,

I'm currently working on a day and night cycle for my project.
The problem is that I get some weird angles after I try to rotate my light.
Atm I calculate the passed seconds with the following formula:

float alreadyPassedSeconds = ((System.DateTime.Now.Hour * 60 * 60) + (System.DateTime.Now.Minute * 60) + System.DateTime.Now.Second);

After that I take that float and multiply it with the degrees per second:
float startRotation = DEGREES_PER_SECOND * alreadyPassedSeconds;

And after that I simply rotate my sun/light on the x-axis to that value:
sun.transform.rotation = Quaternion.Euler(startRotation, 0, 0);

After I started my program at Hour: 16 Minute: 43 Second: 22 I get the startrotation of 250.8417.
So the values are fine but the rotation of the light is at 289.1565 and the scene is dark.

Where is my misconception?

Code (CSharp):
1. using UnityEngine;
2.
3. public class DayAndNightCicleScript : MonoBehaviour {
4.   public GameObject sun;
5.
6.   private const float SECONDSOFADAY = 86400;
7.   private const float SECOND = 1;
8.   private const float MINUTE = 60 * SECOND;
9.   private const float HOUR = 60 * MINUTE;
10.   private const float DAY = 24 * HOUR;
11.
12.   private const float DEGREES_PER_SECOND = 360 / SECONDSOFADAY;
13.
14.   private float _SessionTime;
15.
16.    // Use this for initialization
17.    void Start () {
18.   Debug.Log("Hour: " + System.DateTime.Now.Hour + " Minute: " + System.DateTime.Now.Minute + " Second: " + System.DateTime.Now.Second);
19.   float alreadyPassedSeconds = ((System.DateTime.Now.Hour * 60 * 60) + (System.DateTime.Now.Minute * 60)  + System.DateTime.Now.Second);
20.   float startRotation = DEGREES_PER_SECOND * alreadyPassedSeconds;
21.   Debug.Log("StartRotation: " + startRotation);
22.   sun.transform.rotation = Quaternion.Euler(startRotation, 0, 0);
23.
24.   _SessionTime = 0;
25.   }
26.
27.   // Update is called once per frame
28.   void Update() {
29.   sun.transform.Rotate(new Vector3(DEGREES_PER_SECOND, 0, 0) * Time.deltaTime);
30.   _SessionTime += Time.deltaTime;
31.    }
32. }
33.

2. ### StarManta

Joined:
Oct 23, 2006
Posts:
7,195
There seems to be a rash of issues with Euler angle lately. I never use them, myself, because they are sometimes counterintuitive. Try using Quaternion.AngleAxis instead. (Euler angles are just multiple AngleAxis calls really, only they don't always rotate quite intuitively. I find it more natural to call AngleAxis several times and * the results together.)

(In particular, I can't help but notice the mathematical symmetry of your chosen test value and its result. 289.1565 ~= 540 - 250.8417. I'd bet good money that (actual result) = 540 - (expected result) holds true for at least that "quadrant" of rotation and probably beyond, and similarly patterned for other quadrants as well. That's basically an inversion as well as an "off by 180" error, both of which could be easily explained with unexpected Euler conversions.)

I suspect that your problem in this case is more with the setup of your light object than the script.

3. ### PrieDayThor

Joined:
Jun 18, 2015
Posts:
16
Hey,

Now I tried:
sun.transform.rotation = Quaternion.AngleAxis(startRotation, Vector3.right);

But the result is the same. Hour: 12 Minute: 13 Second: 52 which would be an angle of 183.4667 somehow 'evolves' to 356.5318. I dont get it. My light is the standard light of a new generated scene but I think that none of it's options has something to do with the axis.. so what now?
I honestly don't get it..

4. ### StarManta

Joined:
Oct 23, 2006
Posts:
7,195
Try using a different axis (like .left, maybe?)

5. ### PrieDayThor

Joined:
Jun 18, 2015
Posts:
16
Doesn't work.
I also tried adding or substracting of 180 but it also doesn't work.
Tried something like this:

Code (CSharp):
1. int counter = (int)startRotation;
2.         for(int i = 0; i < counter; i++)
3.         {
4.             sun.transform.Rotate(Vector3.right);
5.         }
still the same result.

6. ### jmjd

Joined:
Nov 14, 2012
Posts:
45
I think you need an offset that is the time of day when the sun object's rotation is zero. So in an empty scene, if I set the sun's rotation to zeros, then I see that the light's direction is heading down the z-axis. This roughly corresponds to 6 a.m. (If the light is pointing forward, it's dawn ~6 a.m., if it's straight down, it's noon, etc.)

Here's the additions to your script to account for this, I added the START_OF_DAY_OFFSET on line 13, and I'm using it on line 23:
Code (CSharp):
1. using UnityEngine;
2.
3. public class DayAndNightCicleScript : MonoBehaviour
4. {
5.     public GameObject sun;
6.
7.     private const float SECONDSOFADAY = 86400f;
8.     private const float SECOND = 1f;
9.     private const float MINUTE = 60f * SECOND;
10.     private const float HOUR = 60f * MINUTE;
11.     private const float DAY = 24f * HOUR;
12.
13.     private const float START_OF_DAY_OFFSET = 6f * HOUR;
14.
15.     private const float DEGREES_PER_SECOND = 360f / SECONDSOFADAY;
16.
17.     private float _SessionTime;
18.
19.     // Use this for initialization
20.     void Start()
21.     {
22.         Debug.Log("Hour: " + System.DateTime.Now.Hour + " Minute: " + System.DateTime.Now.Minute + " Second: " + System.DateTime.Now.Second);
23.         float alreadyPassedSeconds = ((System.DateTime.Now.Hour * 60 * 60) + (System.DateTime.Now.Minute * 60)  + System.DateTime.Now.Second) - START_OF_DAY_OFFSET;
24.         float startRotation = DEGREES_PER_SECOND * alreadyPassedSeconds;
25.         Debug.Log("StartRotation: " + startRotation);
26.         sun.transform.rotation = Quaternion.Euler(startRotation, 0, 0);
27.
28.         _SessionTime = 0;
29.     }
30.
31.     // Update is called once per frame
32.     void Update()
33.     {
34.         sun.transform.Rotate(new Vector3(DEGREES_PER_SECOND, 0, 0) * Time.deltaTime);
35.         _SessionTime += Time.deltaTime;
36.     }
37. }
38.
For me this seems to set the sun's direction at around the right time for me (16 hours, 22 minutes). Hope this helps!

7. ### jister

Joined:
Oct 9, 2009
Posts:
1,719
you can always get the position like this:
where center is de transform the script is on, and raduis the distance between your sun and the center
Code (CSharp):
1. Vector3 UpdatePosition()
2.     {
3.         Vector3 position;
4.
8.         position = new Vector3(center.x, y, z)+offset;
9.         return position;
10.     }

8. ### PrieDayThor

Joined:
Jun 18, 2015
Posts:
16
Hey jmjd,

I tried your code and it seems to work. Unfortunately in game mode the sun freezes at 90 degrees.
Here is another thing. In editor mode I can rotate the light around the x axis freely. In game mode I can rotate between 90 - 360 - 270 degrees. Sometimes I can rotate after 270 degrees and sometimes not.
That's all really weird...

9. ### PrieDayThor

Joined:
Jun 18, 2015
Posts:
16
So Guys,

since I can't get it to work I decided to cut this "feature". This is my code now:
Code (CSharp):
1.
2. using UnityEngine;
3.
4. public class DayAndNightCicleScript : MonoBehaviour
5. {
6.   public GameObject sun;
7.
8.   private const float MORNING = 30F;
9.   private const float NOON = 90F;
10.   private const float EVENING = 170F;
11.
12.   private int lastHour;
13.   private float _SessionTime;
14.
15.   // Use this for initialization
16.   void Start()
17.   {
18.   setSun(System.DateTime.Now.Hour);
19.   _SessionTime = 0;
20.   }
21.
22.   // Update is called once per frame
23.   void Update()
24.   {
25.   if(System.DateTime.Now.Hour != lastHour)
26.   {
27.   setSun(System.DateTime.Now.Hour);
28.   }
29.
30.   _SessionTime += Time.deltaTime;
31.   }
32.
33.   void setSun(int currentHour)
34.   {
35.   if (currentHour < 12 && currentHour > 6)
36.   {
37.   sun.transform.rotation = Quaternion.Euler(MORNING, 0, 0);
38.   }
39.   else if (currentHour < 18 && currentHour > 12)
40.   {
41.   sun.transform.rotation = Quaternion.Euler(NOON, 0, 0);
42.   }
43.   else if (currentHour < 24 && currentHour > 18)
44.   {
45.   sun.transform.rotation = Quaternion.Euler(EVENING, 0, 0);
46.   }
47.   else
48.   {
49.   sun.transform.rotation = Quaternion.Euler(360, 0, 0);
50.   }
51.
52.   lastHour = currentHour;
53.   }
54. }
55.
56.
Had to get the values for the sun out of the game mode because there is a big difference between values of light in game and editor mode.
I hope that someday someone can bring clarity to this matter.

Joined:
Oct 9, 2009
Posts:
1,719
unityunity