Skip to content

Instantly share code, notes, and snippets.

@paulhayes
Last active February 25, 2024 19:06
Show Gist options
  • Star 37 You must be signed in to star a gist
  • Fork 9 You must be signed in to fork a gist
  • Save paulhayes/54a7aa2ee3cccad4d37bb65977eb19e2 to your computer and use it in GitHub Desktop.
Save paulhayes/54a7aa2ee3cccad4d37bb65977eb19e2 to your computer and use it in GitHub Desktop.
Rotates a Unity directional light based on location and time. Includes time scale, and frame stepping for continuous use.
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Entropedia
{
[RequireComponent(typeof(Light))]
[ExecuteInEditMode]
public class Sun : MonoBehaviour
{
[SerializeField]
float longitude;
[SerializeField]
float latitude;
[SerializeField]
[Range(0, 24)]
int hour;
[SerializeField]
[Range(0, 60)]
int minutes;
DateTime time;
Light light;
[SerializeField]
float timeSpeed = 1;
[SerializeField]
int frameSteps = 1;
int frameStep;
[SerializeField]
DateTime date;
public void SetTime(int hour, int minutes) {
this.hour = hour;
this.minutes = minutes;
OnValidate();
}
public void SetLocation(float longitude, float latitude){
this.longitude = longitude;
this.latitude = latitude;
}
public void SetDate(DateTime dateTime){
this.hour = dateTime.Hour;
this.minutes = dateTime.Minute;
this.date = dateTime.Date;
OnValidate();
}
public void SetUpdateSteps(int i) {
frameSteps = i;
}
public void SetTimeSpeed(float speed) {
timeSpeed = speed;
}
private void Awake()
{
light = GetComponent<Light>();
time = DateTime.Now;
hour = time.Hour;
minutes = time.Minute;
date = time.Date;
}
private void OnValidate()
{
time = date + new TimeSpan(hour, minutes, 0);
Debug.Log(time);
}
private void Update()
{
time = time.AddSeconds(timeSpeed * Time.deltaTime);
if (frameStep==0) {
SetPosition();
}
frameStep = (frameStep + 1) % frameSteps;
}
void SetPosition()
{
Vector3 angles = new Vector3();
double alt;
double azi;
SunPosition.CalculateSunPosition(time, (double)latitude, (double)longitude, out azi, out alt);
angles.x = (float)alt * Mathf.Rad2Deg;
angles.y = (float)azi * Mathf.Rad2Deg;
//UnityEngine.Debug.Log(angles);
transform.localRotation = Quaternion.Euler(angles);
light.intensity = Mathf.InverseLerp(-12, 0, angles.x);
}
}
/*
* The following source came from this blog:
* http://guideving.blogspot.co.uk/2010/08/sun-position-in-c.html
*/
public static class SunPosition
{
private const double Deg2Rad = Math.PI / 180.0;
private const double Rad2Deg = 180.0 / Math.PI;
/*!
* \brief Calculates the sun light.
*
* CalcSunPosition calculates the suns "position" based on a
* given date and time in local time, latitude and longitude
* expressed in decimal degrees. It is based on the method
* found here:
* http://www.astro.uio.no/~bgranslo/aares/calculate.html
* The calculation is only satisfiably correct for dates in
* the range March 1 1900 to February 28 2100.
* \param dateTime Time and date in local time.
* \param latitude Latitude expressed in decimal degrees.
* \param longitude Longitude expressed in decimal degrees.
*/
public static void CalculateSunPosition(
DateTime dateTime, double latitude, double longitude, out double outAzimuth, out double outAltitude)
{
// Convert to UTC
dateTime = dateTime.ToUniversalTime();
// Number of days from J2000.0.
double julianDate = 367 * dateTime.Year -
(int)((7.0 / 4.0) * (dateTime.Year +
(int)((dateTime.Month + 9.0) / 12.0))) +
(int)((275.0 * dateTime.Month) / 9.0) +
dateTime.Day - 730531.5;
double julianCenturies = julianDate / 36525.0;
// Sidereal Time
double siderealTimeHours = 6.6974 + 2400.0513 * julianCenturies;
double siderealTimeUT = siderealTimeHours +
(366.2422 / 365.2422) * (double)dateTime.TimeOfDay.TotalHours;
double siderealTime = siderealTimeUT * 15 + longitude;
// Refine to number of days (fractional) to specific time.
julianDate += (double)dateTime.TimeOfDay.TotalHours / 24.0;
julianCenturies = julianDate / 36525.0;
// Solar Coordinates
double meanLongitude = CorrectAngle(Deg2Rad *
(280.466 + 36000.77 * julianCenturies));
double meanAnomaly = CorrectAngle(Deg2Rad *
(357.529 + 35999.05 * julianCenturies));
double equationOfCenter = Deg2Rad * ((1.915 - 0.005 * julianCenturies) *
Math.Sin(meanAnomaly) + 0.02 * Math.Sin(2 * meanAnomaly));
double elipticalLongitude =
CorrectAngle(meanLongitude + equationOfCenter);
double obliquity = (23.439 - 0.013 * julianCenturies) * Deg2Rad;
// Right Ascension
double rightAscension = Math.Atan2(
Math.Cos(obliquity) * Math.Sin(elipticalLongitude),
Math.Cos(elipticalLongitude));
double declination = Math.Asin(
Math.Sin(rightAscension) * Math.Sin(obliquity));
// Horizontal Coordinates
double hourAngle = CorrectAngle(siderealTime * Deg2Rad) - rightAscension;
if (hourAngle > Math.PI)
{
hourAngle -= 2 * Math.PI;
}
double altitude = Math.Asin(Math.Sin(latitude * Deg2Rad) *
Math.Sin(declination) + Math.Cos(latitude * Deg2Rad) *
Math.Cos(declination) * Math.Cos(hourAngle));
// Nominator and denominator for calculating Azimuth
// angle. Needed to test which quadrant the angle is in.
double aziNom = -Math.Sin(hourAngle);
double aziDenom =
Math.Tan(declination) * Math.Cos(latitude * Deg2Rad) -
Math.Sin(latitude * Deg2Rad) * Math.Cos(hourAngle);
double azimuth = Math.Atan(aziNom / aziDenom);
if (aziDenom < 0) // In 2nd or 3rd quadrant
{
azimuth += Math.PI;
}
else if (aziNom < 0) // In 4th quadrant
{
azimuth += 2 * Math.PI;
}
outAltitude = altitude;
outAzimuth = azimuth;
}
/*!
* \brief Corrects an angle.
*
* \param angleInRadians An angle expressed in radians.
* \return An angle in the range 0 to 2*PI.
*/
private static double CorrectAngle(double angleInRadians)
{
if (angleInRadians < 0)
{
return 2 * Math.PI - (Math.Abs(angleInRadians) % (2 * Math.PI));
}
else if (angleInRadians > 2 * Math.PI)
{
return angleInRadians % (2 * Math.PI);
}
else
{
return angleInRadians;
}
}
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Entropedia
{
public class SunSetDate : MonoBehaviour
{
public Sun sun;
public int year = 2020;
[Range(1, 12)]
public int month = 1;
[Range(0, 31)]
public int day = 1;
private void OnValidate()
{
try{
DateTime d = new DateTime(year,month,day,DateTime.Now.Hour,DateTime.Now.Minute,0);
Debug.Log(d);
if(sun) sun.SetDate(d);
}
catch(System.ArgumentOutOfRangeException e){
Debug.LogWarning("bad date");
}
}
}
}
using UnityEngine;
using System.Collections;
namespace Entropedia {
public class SunSetLocation : MonoBehaviour
{
[SerializeField]
Sun sun;
public void Start()
{
StartCoroutine(SetLocation());
}
public IEnumerator SetLocation()
{
if (!Input.location.isEnabledByUser){
Debug.LogWarning("location disabled by user");
yield break;
}
Input.location.Start();
while (Input.location.status == LocationServiceStatus.Initializing){
yield return new WaitForSeconds(0.5f);
}
if (Input.location.status == LocationServiceStatus.Failed){
Debug.LogWarning("Unable to determine device location");
yield break;
}
if(Input.location.status==LocationServiceStatus.Running){
var locInfo = Input.location.lastData;
Debug.LogFormat("long={0} lat={1}",locInfo.longitude,locInfo.latitude);
sun.SetLocation( locInfo.longitude, locInfo.latitude );
}
Input.location.Stop();
}
}
}
@paulhayes
Copy link
Author

paulhayes commented Mar 3, 2021 via email

@bartburkhardt
Copy link

Hi Paul, it looks like it's not a bug after all. The sun glitch has to do with the daylighting saving that occurs on march 28-29

@TheGeekyDead
Copy link

Hello, I just found your script and it works great but I have a question.
Would it be possible to have it change the skybox/brightness once it reaches a low point?

I was having a hard time setting something up myself, I was going to just make different scenes day or night.
But thank you, I will give you full credit in the credits under Programming/Scripts, if you don't mind me using it.

@paulhayes
Copy link
Author

It's here for anyone to use. The credit is welcome, that's very nice of you.

I'm not sure what feature you were asking for, however I don't have time to make bespoke modifications for people.

If you explain what you are looking for in more detail perhaps I can point you in the right direction.

@TheGeekyDead
Copy link

TheGeekyDead commented Jun 27, 2021

It's here for anyone to use. The credit is welcome, that's very nice of you.

I'm not sure what feature you were asking for, however I don't have time to make bespoke modifications for people.

If you explain what you are looking for in more detail perhaps I can point you in the right direction.

Edit: (After taking my Adderall)
I was being retarded... I solved it by calling it from the sun.cs. It is the one handling the hour/rotation, not it correctly updates the UI.Tex Hour/Min and swaps the Skybox when it hit's 10PM. I got that working, thanks for script helping me get started learning it.

I know what I added is not, what's the term? Efficient? But maybe you can point me in the right direction for making it more optimal.

//MY EDIT
			CurrentHour.text = (time.Hour).ToString();
			CurrentMinutes.text = (time.Minute).ToString();
			daytext.text = (DateVal).ToString();
			monthtext.text = (this.date.Month).ToString();
			yeartext.text = (this.date.Year).ToString();
			//Debug.Log(timeticker);
			
			//EDIT SKYBOX
			if (time.Hour == 6 || time.Hour == 7 || time.Hour == 8 || time.Hour == 9 || time.Hour == 10 || time.Hour == 11 || time.Hour == 12 || time.Hour == 13 || time.Hour == 14 || time.Hour == 15 || time.Hour == 16 || time.Hour == 17 || time.Hour == 18){
				RenderSettings.skybox = mat1;
				//Debug.Log(RenderSettings.skybox);
				DynamicGI.UpdateEnvironment();
			}
			if (time.Hour == 19 || time.Hour == 20 || time.Hour == 21 || time.Hour == 22 || time.Hour == 23 || time.Hour == 0 || time.Hour == 1 || time.Hour == 2 || time.Hour == 3 || time.Hour == 4 || time.Hour == 5){
				RenderSettings.skybox = mat2;
				DynamicGI.UpdateEnvironment();
			}
			//UPDATE DAY COUNT
			if (time.Hour == 0){
				DateVal = +1;
				DynamicGI.UpdateEnvironment();
			}
			// EDIT AM/PM
			if (time.Hour == 0 || time.Hour == 1 || time.Hour == 2 || time.Hour == 3 || time.Hour == 4 || time.Hour == 5 || time.Hour == 6 || time.Hour == 7 || time.Hour == 8 || time.Hour == 9 || time.Hour == 10 || time.Hour == 11){
				AmPm.text = "AM";
				DynamicGI.UpdateEnvironment();
			}
			if (time.Hour == 12 || time.Hour == 13 || time.Hour == 14 || time.Hour == 15 || time.Hour == 16 || time.Hour == 17 || time.Hour == 18 || time.Hour == 19 || time.Hour == 20 || time.Hour == 21 || time.Hour == 22 || time.Hour == 23){
				AmPm.text = "PM";
				DynamicGI.UpdateEnvironment();
			}

@TheGeekyDead
Copy link

TheGeekyDead commented Jun 29, 2021

If anything, I can pay you to help me add those two things correctly, Or at leas make my additional code not so noobish so I can track the current time.

@paulhayes
Copy link
Author

paulhayes commented Jun 29, 2021

"I was being retarded... I solved it by calling it from the sun.cs. It is the one handling the hour/rotation."

So what features are you looking for still? I'm away on holiday for a week but can take a look when I get back.

@TheGeekyDead
Copy link

TheGeekyDead commented Jun 30, 2021

"I was being retarded... I solved it by calling it from the sun.cs. It is the one handling the hour/rotation."

So what features are you looking for still? I'm away on holiday for a week but can take a look when I get back.

Oh, hope you hare having a good vacation.
I just having issues using the Hour,Minute,Date being called on the UI. I'm not sure how to call it so it displays correctly. I want to be able to display the current time and date on the UI.Text elements..
And then when it rolls over from 23 to 0 it adds +1 days to the UI. And being able to reference the current time "Hour, I can toggle light's On/Off.

So far the only thing I have gotten to work right is the skybox changing when it hits night time. The day does update, but it adds multiple +1 to it.
TimeDate-ToUIError2

But here is the Sun.cs with my edits. Don't laugh lol.

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

namespace Entropedia
{

    [RequireComponent(typeof(Light))]
    [ExecuteInEditMode]
    public class Sun : MonoBehaviour
    {
        [SerializeField]
        float longitude;

        [SerializeField]
        float latitude;

        [SerializeField]
        [Range(0, 24)]
        int hour;

        [SerializeField]
        [Range(0, 60)]
        int minutes;

        DateTime time;
        Light light;
		public Text daytext;
		public Text monthtext;
		public Text yeartext;
		public Text CurrentHour;
		public Text CurrentMinutes;
		public Text AmPm;
		public GameObject NightAmbience;
		
		//SKYBOX SWITCHER
		public Material mat1;
		public Material mat2;

        [SerializeField]
        float timeSpeed = 1;

        [SerializeField]
        int frameSteps = 1;
        int frameStep;

        [SerializeField]
        DateTime date;

        public void SetTime(int hour, int minutes) {
            this.hour = hour;
            this.minutes = minutes;            
            OnValidate();
        }

        public void SetLocation(float longitude, float latitude){
          this.longitude = longitude;
          this.latitude = latitude;
        }

        public void SetDate(DateTime dateTime){
         this.hour = dateTime.Hour;
         this.minutes = dateTime.Minute;
         this.date = dateTime.Date;
         OnValidate();
        }

        public void SetUpdateSteps(int i) {
            frameSteps = i;
        }

        public void SetTimeSpeed(float speed) {
            timeSpeed = speed;
        }

        private void Awake()
        {

            light = GetComponent<Light>();
            time = DateTime.Now;
            hour = time.Hour;
            minutes = time.Minute;
            date = time.Date;
        }
		
		//DATE CONTROLER
		//SetDate sn = gameObject.GetComponent<SetDate>();
		public int DateVal = 1;
		public int MonthVal = 1;
		//(this.date.Month).ToString()
		//myScript.GetComponent<SetDate>().Month

        private void OnValidate()
        {
            time = date + new TimeSpan(hour, minutes, 0);

            Debug.Log(time);
        }

        private void UpdateDay(){
			DateVal = DateVal+1;
		}
		
		private void UpdateMonth(){
			MonthVal = MonthVal=1;
		}
		
		private void Update()
        {
            time = time.AddSeconds(timeSpeed * Time.deltaTime);
            if (frameStep==0) {
                SetPosition();
            }
            frameStep = (frameStep + 1) % frameSteps;
			
			//MY EDIT
			CurrentHour.text = (time.Hour).ToString();
			CurrentMinutes.text = (time.Minute).ToString();
			daytext.text = (DateVal).ToString();
			monthtext.text = (MonthVal).ToString();
			yeartext.text = (this.date.Year).ToString();
			//Debug.Log(timeticker);
			
			//EDIT SKYBOX
			if (time.Hour == 6 || time.Hour == 7 || time.Hour == 8 || time.Hour == 9 || time.Hour == 10 || time.Hour == 11 || time.Hour == 12 || time.Hour == 13 || time.Hour == 14 || time.Hour == 15 || time.Hour == 16 || time.Hour == 17 || time.Hour == 18){
				RenderSettings.skybox = mat1;
				NightAmbience.SetActive(false);
				//Debug.Log(RenderSettings.skybox);
				DynamicGI.UpdateEnvironment();
			}
			if (time.Hour == 19 || time.Hour == 20 || time.Hour == 21 || time.Hour == 22 || time.Hour == 23 || time.Hour == 0 || time.Hour == 1 || time.Hour == 2 || time.Hour == 3 || time.Hour == 4 || time.Hour == 5){
				RenderSettings.skybox = mat2;
				NightAmbience.SetActive(true);
				DynamicGI.UpdateEnvironment();
			}
			//UPDATE DAY COUNT
			if (time.Hour == 0 && time.Minute == 1){
				UpdateDay();
				//DynamicGI.UpdateEnvironment();
			}
			// EDIT AM/PM
			if (time.Hour == 0 || time.Hour == 1 || time.Hour == 2 || time.Hour == 3 || time.Hour == 4 || time.Hour == 5 || time.Hour == 6 || time.Hour == 7 || time.Hour == 8 || time.Hour == 9 || time.Hour == 10 || time.Hour == 11){
				AmPm.text = "AM";
				DynamicGI.UpdateEnvironment();
			}
			if (time.Hour == 12 || time.Hour == 13 || time.Hour == 14 || time.Hour == 15 || time.Hour == 16 || time.Hour == 17 || time.Hour == 18 || time.Hour == 19 || time.Hour == 20 || time.Hour == 21 || time.Hour == 22 || time.Hour == 23){
				AmPm.text = "PM";
				DynamicGI.UpdateEnvironment();
			}

        }

        void SetPosition()
        {

            Vector3 angles = new Vector3();
            double alt;
            double azi;
            SunPosition.CalculateSunPosition(time, (double)latitude, (double)longitude, out azi, out alt);
            angles.x = (float)alt * Mathf.Rad2Deg;
            angles.y = (float)azi * Mathf.Rad2Deg;
            //UnityEngine.Debug.Log(angles);
            transform.localRotation = Quaternion.Euler(angles);
            light.intensity = Mathf.InverseLerp(-12, 0, angles.x);
        }

        
    }

    /*
     * The following source came from this blog:
     * http://guideving.blogspot.co.uk/2010/08/sun-position-in-c.html
     */
    public static class SunPosition
    {
        private const double Deg2Rad = Math.PI / 180.0;
        private const double Rad2Deg = 180.0 / Math.PI;

        /*! 
         * \brief Calculates the sun light. 
         * 
         * CalcSunPosition calculates the suns "position" based on a 
         * given date and time in local time, latitude and longitude 
         * expressed in decimal degrees. It is based on the method 
         * found here: 
         * http://www.astro.uio.no/~bgranslo/aares/calculate.html 
         * The calculation is only satisfiably correct for dates in 
         * the range March 1 1900 to February 28 2100. 
         * \param dateTime Time and date in local time. 
         * \param latitude Latitude expressed in decimal degrees. 
         * \param longitude Longitude expressed in decimal degrees. 
         */
        public static void CalculateSunPosition(
            DateTime dateTime, double latitude, double longitude, out double outAzimuth, out double outAltitude)
        {
            // Convert to UTC  
            dateTime = dateTime.ToUniversalTime();

            // Number of days from J2000.0.  
            double julianDate = 367 * dateTime.Year -
                (int)((7.0 / 4.0) * (dateTime.Year +
                (int)((dateTime.Month + 9.0) / 12.0))) +
                (int)((275.0 * dateTime.Month) / 9.0) +
                dateTime.Day - 730531.5;

            double julianCenturies = julianDate / 36525.0;

            // Sidereal Time  
            double siderealTimeHours = 6.6974 + 2400.0513 * julianCenturies;

            double siderealTimeUT = siderealTimeHours +
                (366.2422 / 365.2422) * (double)dateTime.TimeOfDay.TotalHours;

            double siderealTime = siderealTimeUT * 15 + longitude;

            // Refine to number of days (fractional) to specific time.  
            julianDate += (double)dateTime.TimeOfDay.TotalHours / 24.0;
            julianCenturies = julianDate / 36525.0;

            // Solar Coordinates  
            double meanLongitude = CorrectAngle(Deg2Rad *
                (280.466 + 36000.77 * julianCenturies));

            double meanAnomaly = CorrectAngle(Deg2Rad *
                (357.529 + 35999.05 * julianCenturies));

            double equationOfCenter = Deg2Rad * ((1.915 - 0.005 * julianCenturies) *
                Math.Sin(meanAnomaly) + 0.02 * Math.Sin(2 * meanAnomaly));

            double elipticalLongitude =
                CorrectAngle(meanLongitude + equationOfCenter);

            double obliquity = (23.439 - 0.013 * julianCenturies) * Deg2Rad;

            // Right Ascension  
            double rightAscension = Math.Atan2(
                Math.Cos(obliquity) * Math.Sin(elipticalLongitude),
                Math.Cos(elipticalLongitude));

            double declination = Math.Asin(
                Math.Sin(rightAscension) * Math.Sin(obliquity));

            // Horizontal Coordinates  
            double hourAngle = CorrectAngle(siderealTime * Deg2Rad) - rightAscension;

            if (hourAngle > Math.PI)
            {
                hourAngle -= 2 * Math.PI;
            }

            double altitude = Math.Asin(Math.Sin(latitude * Deg2Rad) *
                Math.Sin(declination) + Math.Cos(latitude * Deg2Rad) *
                Math.Cos(declination) * Math.Cos(hourAngle));

            // Nominator and denominator for calculating Azimuth  
            // angle. Needed to test which quadrant the angle is in.  
            double aziNom = -Math.Sin(hourAngle);
            double aziDenom =
                Math.Tan(declination) * Math.Cos(latitude * Deg2Rad) -
                Math.Sin(latitude * Deg2Rad) * Math.Cos(hourAngle);

            double azimuth = Math.Atan(aziNom / aziDenom);

            if (aziDenom < 0) // In 2nd or 3rd quadrant  
            {
                azimuth += Math.PI;
            }
            else if (aziNom < 0) // In 4th quadrant  
            {
                azimuth += 2 * Math.PI;
            }

            outAltitude = altitude;
            outAzimuth = azimuth;
        }

        /*! 
        * \brief Corrects an angle. 
        * 
        * \param angleInRadians An angle expressed in radians. 
        * \return An angle in the range 0 to 2*PI. 
        */
        private static double CorrectAngle(double angleInRadians)
        {
            if (angleInRadians < 0)
            {
                return 2 * Math.PI - (Math.Abs(angleInRadians) % (2 * Math.PI));
            }
            else if (angleInRadians > 2 * Math.PI)
            {
                return angleInRadians % (2 * Math.PI);
            }
            else
            {
                return angleInRadians;
            }
        }
    }

}

@zoran-petrovic-87
Copy link

Hi @paulhayes, first of all, thank you for this script!
I have one question regarding position of directional light.
This script will only rotate the light, so we need to set it's position. I assume it must be located at X=0, Z=0, and Y can be any large number (e.g. 4000)?

@paulhayes
Copy link
Author

Hi @paulhayes, first of all, thank you for this script! I have one question regarding position of directional light. This script will only rotate the light, so we need to set it's position. I assume it must be located at X=0, Z=0, and Y can be any large number (e.g. 4000)?

Directional lights in Unity do not use their position in the lighting calculations. All light rays are considered parallel, i.e from a source infinitely far away.

Hope you find the script useful!

@zoran-petrovic-87
Copy link

@paulhayes Thanks, it makes sense now :) I am new to Unity and this script is very useful. I will credit you (if I ever manage to complete my project).

@DelonLim
Copy link

Hi @paulhayes, I am currently developing project for school project, not sure about the licenses on github, would like to ask whether I could use your code for my project?

@paulhayes
Copy link
Author

Hi @DelonLim , it's public domain. I hope you find it useful.

@DelonLim
Copy link

@paulhayes Thanks I will still credit you :)

@beejay1129
Copy link

Hi Paul, Thanks for this amazing script! I'm trying to add some Inputs to move the Directional Light by changing the time and date variables in your script. I use Input.GetButton("A") to change the hours in the Sun.cs script to change time and it works fine but when I use the Input.GetButton("B") in the SetDate.cs to change the date, there is no recognition of any void update() code in that script. On another note, there is a missing check box next to SetDate.cs which from my research means that there are no frame based mono behavior associated with that script. I think whatever is causing the lack of checkbox might be the issue... any help would be greatly appreciated!

image

@paulhayes
Copy link
Author

paulhayes commented Aug 2, 2022 via email

@paulhayes
Copy link
Author

Your void update method in SetDate is lower case. It needs to be void Update

@beejay1129
Copy link

Your void update method in SetDate is lower case. It needs to be void Update

OMG! thank you!

@BikutaAnkuta
Copy link

Hi @paulhayes thanks for sharing this great tool with everyone.

I wanted to know if you had any progress on this with matching timezones using lat/lon? As some have previously said, there appears to be a lot of APIs that you can call to get the correct UTC offset, but I'm looking for an offline solution somehow.

@suniqo
Copy link

suniqo commented Nov 28, 2022

Hello, @paulhayes love your script, it is extremely useful, thank you for sharing it,
I was wondering where is the north located in your coordinate system. Could you help me out?

@real-esekyl
Copy link

This is awesome, I use this to simulate shadows thrown by neighboring roofs to optimize solar projects. Thanks so much! I am not too familiar with Unity yet, so could someone maybe help me with animating only a special timeframe, lets say one day of each month, only daytime timewarps?

Would I need to edit the scripts into a for-loop for each month and put into that one a loop with the time increasing from lets say 6 am to 10pm or is there a better way?

Thank you very much in advance!

grafik

@paulhayes
Copy link
Author

Hello, @paulhayes love your script, it is extremely useful, thank you for sharing it, I was wondering where is the north located in your coordinate system. Could you help me out?

Could you qualify that. Do you mean you want North relative to Unity's global Euclidian coordinates?

@paulhayes
Copy link
Author

paulhayes commented Dec 9, 2022

This is awesome, I use this to simulate shadows thrown by neighboring roofs to optimize solar projects. Thanks so much! I am not too familiar with Unity yet, so could someone maybe help me with animating only a special timeframe, lets say one day of each month, only daytime timewarps?

Would I need to edit the scripts into a for-loop for each month and put into that one a loop with the time increasing from lets say 6 am to 10pm or is there a better way?

Thank you very much in advance!

grafik

I suggest you create a new Monobehaviour that has a reference to the Sun class, and calls Sun.SetDate at the times you would like.
Create a coroutine that has your while loop, and have that coroutine have a WaitForSeconds to add a delay between calls.

Please be aware this code is not tested to be accurate in real world scenarios. Please test it's reliability for your needs.

@paulhayes
Copy link
Author

Hi @paulhayes thanks for sharing this great tool with everyone.

I wanted to know if you had any progress on this with matching timezones using lat/lon? As some have previously said, there appears to be a lot of APIs that you can call to get the correct UTC offset, but I'm looking for an offline solution somehow.

I don't have time at present. I suggest you use: https://github.com/mattjohnsonpint/GeoTimeZone/tree/4.1.0

Please let me know if you achieve this, and make a pull request so I can add this feature in for other people to use.

@JWongRBG
Copy link

JWongRBG commented Feb 6, 2023

Hello, @paulhayes love your script, it is extremely useful, thank you for sharing it, I was wondering where is the north located in your coordinate system. Could you help me out?

Could you qualify that. Do you mean you want North relative to Unity's global Euclidian coordinates?

I would like to know this too - right now i am guessing either negative X or Z, but there seems to be no good way to test and see which way is north.

I would to thank you for making this script, it will be really useful for archviz projects where the sun direction matters!

@JWongRBG
Copy link

JWongRBG commented Feb 9, 2023

im testing this script against other sun calculators and it seems to yield incorrect results:

in the following example i am using -33.85158051,151.21092364 as longitude and latitude respectively.

this is the reference - http://andrewmarsh.com/apps/staging/sunpath3d.html :
image

image

and this is the script:
image

image

the shadow directions are completely different, no matter which direction i look at the scene from the sun position doesnt line up at all. is there something i am missing? thanks!

@paulhayes
Copy link
Author

im testing this script against other sun calculators and it seems to yield incorrect results:

in the following example i am using -33.85158051,151.21092364 as longitude and latitude respectively.

this is the reference - http://andrewmarsh.com/apps/staging/sunpath3d.html : image

image

and this is the script: image

image

the shadow directions are completely different, no matter which direction i look at the scene from the sun position doesnt line up at all. is there something i am missing? thanks!

So firstly +Z is North.
You might be having problems because the DateTime of the Sun is in UTC. It has no concept of timezones. So please take you regions time, and offset it to UTC, and then input it into Sun.cs.

I hope that helps.

ps if you are still finding inaccuracies after making these changes please investigate and help me improve this code. Open source needs you!

@Rairey233
Copy link

Rairey233 commented Jun 16, 2023

@paulhayes Hello , I'm not sure how active this thread is anymore, but I've been playing with the script and it doesn't seem to like me inputting my own date and time into the user input i.e it always resets it to the current date and time. Any ideas on how to fix this? I'm trying to essentially use these scripts as part of a simulation, so it isn't particularly useful to have it set to the current datetime. Maybe the order of the scripts is important?

@paulhayes
Copy link
Author

If you are setting your own date, you might want to forego the SetDate component and set the date on the sun directy by calling Sun.SetDate from your own script.

@paulhayes Hello , I'm not sure how active this thread is anymore, but I've been playing with the script and it doesn't seem to like me inputting my own date and time into the user input i.e it always resets it to the current date and time. Any ideas on how to fix this? I'm trying to essentially use these scripts as part of a simulation, so it isn't particularly useful to have it set to the current datetime. Maybe the order of the scripts is important?

@iyed-5
Copy link

iyed-5 commented Jul 11, 2023

great script thank you
but i think i have a problem which is daylight saving time or idk in the summer and in winter its normal hours,my longitude is 10.3
and i want all year +1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment