C#脚本
根据查询文献,真实世界中在地球上某个点作为参考点去描述太阳运行轨迹的决定参数有很多,比如:solar declination(黄赤交角or赤纬角-,取决于所在天数在每年的排序);H(太阳时角,距离12点所运行的角度,e.g.下午一点就是(12-13)*15°),经纬度。
此处就不详细解释了,上C#代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public class SunMove : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
//找太阳,只有一个,所以就直接根据type找
Light lightComponent = FindObjectOfType(typeof(Light)) as Light;
if (lightComponent.type == LightType.Directional)
{
GameObject lightObject = lightComponent.gameObject;
}
else
{
Debug.Log("太阳组件有问题");
}
double[] monthly_solar_declination = new double[] { -20.1, -11.2, 0, 11.6, 20.1, 23.4, 20.4, 11.8, 0, -11.8, -20.4, -23.4 };
int i = 1;
double angle = monthly_solar_declination[i];
double input_latitude = 30;//13:00
double h = 13;
var result = SunPath(input_latitude, angle, h);
float x = (float)result.Item2;
float y = (float)result.Item1;
x = x * 360 / (float)(2 * Math.PI);
y = y * 360 / (float)(2 * Math.PI);
//匹配x,y
Vector3 newRotation = new Vector3(x,y, 0);
lightComponent.transform.rotation = Quaternion.Euler(newRotation);
//Debug.Log(x+","+y);
}
Tuple<double, double> SunPath(double latitude, double solar_declination, double h)
{
double L = latitude * 2 * Math.PI / 360;
double delta = solar_declination * 2 * Math.PI / 360;
// Sun hour, unit is degree
double H = 15 * (12 - h) * 2 * Math.PI / 360;
double beta = Math.Asin(Math.Cos(L) * Math.Cos(delta) * Math.Cos(H) + Math.Sin(L) * Math.Sin(delta));
double phi = Math.Asin(Math.Cos(delta) * Math.Sin(H) / Math.Cos(beta));
return new Tuple<double, double>(phi, beta);
}
// Update is called once per frame
void Update()
{
}
}
在unity中把初始的Directional Light 作为模拟太阳的对象,通过更改Transformer组件的属性rotation,在角坐标维度下去衡量太阳运转。
讲的不是太详细,但是查了太多文章,且主要为记录一个调试很多次才被验证正确的代码结果。真的是投入了很多心血啊(拥抱开源)有问题评论区见,有机会会详细写一篇相关的blog。
注释:代码中i为月份,rotation属性是一个三维向量表征旋转角度,注意脚本要绑定游戏实体。(本段代码可以改在update的生命周期里以达到游戏里实时模拟太阳的效果)
效果展示:
主要通过影子效果展示
shadow At 8:00
shadow at 12:00
shadow at 16:00