问题描述
我一直在关注关于游戏内昼夜循环的两个不同教程。一个是 TimeTickSystem,它使火灾能够作为特定事件点亮。另一个是用于使太阳旋转并在夜晚来临时开始淡入和淡出的 DayNight 循环。现在我希望这两个能很好地一起玩,这样我就可以拥有星星消逝的昼夜循环,以及火焰的开始和停止。
第一个脚本:TimeTickSystem 提供浮动 timeOfDay、OnLightFires 和 OnExtinguishFires 事件以及 public void TestTimeEventsOnSetTime()
第二个脚本:DayNightController 脚本。提供“时间”浮动并以与 TimeTickSystem 的“timeOfDay”相同的方式计算它。我需要这两个脚本能够以它们的时间始终相同并且它们的事件同时发生的方式协同工作。
using System;
using UnityEngine;
public static class TimeTickSystem
{
public class OnTimeEventArgs : EventArgs
{
public float timeOfDay;
}
public static event EventHandler<OnTimeEventArgs> OnLightFires;
public static event EventHandler<OnTimeEventArgs> OnExtinguishFires;
private static GameObject timeTickSystemObject;
private static TimeTickSystemObject timeTickSystemComponent;
private static float timeOfDay,timeOfDayPrevIoUs = 43200f;
private static float secondsPerSecond = 1000;
private static bool areFiresLit;
private static Vector3 hmsOfDay;
public static void Create()
{
if (timeTickSystemObject == null)
{
timeTickSystemObject = new GameObject("TimeTickSystem");
timeTickSystemComponent = timeTickSystemObject.AddComponent<TimeTickSystemObject>();
}
}
public static bool AreFiresLit
{
get { return areFiresLit; }
}
public static float SecondsPerSecond
{
get { return secondsPerSecond; }
set { secondsPerSecond = value; }
}
public static float TimeOfDay
{
get { return timeOfDay; }
set
{
timeOfDay = value;
timeOfDayPrevIoUs = timeOfDay; // Could subtract a very small number;
hmsOfDay = FloatToHMS(timeOfDay);
timeTickSystemComponent.TestTimeEventsOnSetTime();
}
}
public static Vector3 HMSOfDay
{
get { return hmsOfDay; }
set
{
TimeOfDay = HMSToFloat(hmsOfDay.x,hmsOfDay.y,hmsOfDay.z);
}
}
public static float HMSToFloat(float hour,float minute,float second)
{
return 3600f * hour + 60f * minute + second;
}
public static Vector3 FloatToHMS(float time)
{
Vector3 temp = Vector3.zero;
temp.x = Mathf.Floor(time / 3600);
time -= temp.x * 3600f;
temp.y = Mathf.Floor(time / 60);
temp.z = time - temp.y * 60f;
return temp;
}
public static bool TimeFallsBetween(float currentTime,float startTime,float endTime)
{
if (startTime < endTime)
{
if (currentTime >= startTime && currentTime <= endTime) return true;
else return false;
}
else
{
if (currentTime < startTime && currentTime > endTime) return false;
else return true;
}
}
private class TimeTickSystemObject : MonoBehavIoUr
{
private void Update()
{
timeOfDay += Time.deltaTime * secondsPerSecond;
if (timeOfDay > 86400f) // 24 hours * 60 minutes * 60 seconds = 86400 = Midnight
{
//days += 1;
timeOfDay -= 86400f;
}
TestTimeEvents();
timeOfDayPrevIoUs = timeOfDay;
}
public void TestTimeEvents()
{
// You should parameterize these times,or set them from another script
if (timeOfDayPrevIoUs < HMSToFloat(18f,0f,0f) && timeOfDay >= HMSToFloat(18f,0f))
{
//if (OnLightFires != null) OnLightFires(this,new OnTimeEventArgs { timeOfDay = timeOfDay });
OnLightFires?.Invoke(this,new OnTimeEventArgs { timeOfDay = timeOfDay });
areFiresLit = true;
}
if (timeOfDayPrevIoUs < HMSToFloat(6f,0f) && timeOfDay >= HMSToFloat(6f,0f))
{
OnExtinguishFires?.Invoke(this,new OnTimeEventArgs { timeOfDay = timeOfDay });
areFiresLit = false;
}
}
public void TestTimeEventsOnSetTime()
{
// You should parameterize these times,or set them from another script
if (TimeFallsBetween(timeOfDay,HMSToFloat(18f,0f),HMSToFloat(6f,0f)))
{
OnLightFires?.Invoke(this,new OnTimeEventArgs { timeOfDay = timeOfDay });
areFiresLit = true;
}
else
{
OnExtinguishFires?.Invoke(this,new OnTimeEventArgs { timeOfDay = timeOfDay });
areFiresLit = false;
}
}
}
}
using UnityEngine;
using System;
using CodeMonkey.Utils;
public class DayNightController : MonoBehavIoUr
{
[Serializefield] private Transform sunTransform;
[Serializefield] private Light sun;
[Serializefield] private float angleAtNoon;
[Serializefield] private Vector3 hourMinuteSecond = new Vector3(6f,hmsSunSet = new Vector3(18f,0f);
[Serializefield] public int days = 0;
[Serializefield] public float speed = 100;
[Serializefield] private float intensityAtNoon = 1f,intensityAtSunSet = 0.5f;
[Serializefield] private Color fogColorDay = Color.grey,fogColorNight = Color.black;
[Serializefield] private Transform starsTransform;
[Serializefield] private Vector3 hmsstarsLight = new Vector3(19f,30f,hmsstarsExtinguish = new Vector3(03f,0f);
[Serializefield] private float starsFadeInTime = 7200f,starsFadeOutTime = 7200f;
[NonSerialized] public float time;
private float intensity,rotation,prev_rotation = -1f,sunSet,sunRise,sunDayRatio,fade,timeLight,timeExtinguish;
private Color tintColor = new Color(0.5f,0.5f,0.5f);
private Vector3 dir;
private Renderer rend;
void Start()
{
rend = starsTransform.GetComponent<ParticleSystem>().GetComponent<Renderer>();
time = HMS_to_Time(hourMinuteSecond.x,hourMinuteSecond.y,hourMinuteSecond.z);
sunSet = HMS_to_Time(hmsSunSet.x,hmsSunSet.y,hmsSunSet.z);
sunRise = 86400f - sunSet;
sunDayRatio = (sunSet - sunRise) / 43200f;
dir = new Vector3(Mathf.Cos(Mathf.Deg2Rad * angleAtNoon),Mathf.Sin(Mathf.Deg2Rad * angleAtNoon),0f);
//dir = new Vector3(1f,0f);
starsFadeInTime /= speed;
starsFadeOutTime /= speed;
fade = 0;
timeLight = HMS_to_Time(hmsstarsLight.x,hmsstarsLight.y,hmsstarsLight.z);
timeExtinguish = HMS_to_Time(hmsstarsExtinguish.x,hmsstarsExtinguish.y,hmsstarsExtinguish.z);
}
void Update()
{
// normal below
time += Time.deltaTime * speed;
if (time > 86400f)
{
days += 1;
time -= 86400f;
}
if (prev_rotation == -1f)
{
sunTransform.eulerAngles = Vector3.zero;
prev_rotation = 0f;
}
else prev_rotation = rotation;
rotation = (time - 21600f) / 86400f * 360f;
sunTransform.Rotate(dir,rotation - prev_rotation);
starsTransform.Rotate(dir,rotation - prev_rotation);
if (time < sunRise) intensity = intensityAtSunSet * time / sunRise;
else if (time < 43200f) intensity = intensityAtSunSet + (intensityAtNoon - intensityAtSunSet) * (time - sunRise) / (43200f - sunRise);
else if (time < sunSet) intensity = intensityAtNoon - (intensityAtNoon - intensityAtSunSet) * (time - 43200f) / (sunSet - 43200f);
else intensity = intensityAtSunSet - (1f - intensityAtSunSet) * (time - sunSet) / (86400f - sunSet);
RenderSettings.fogColor = Color.Lerp(fogColorNight,fogColorDay,intensity * intensity);
if (sun != null) sun.intensity = intensity;
if (Time_Falls_Between(time,timeExtinguish))
{
fade += Time.deltaTime / starsFadeInTime;
if (fade > 1f) fade = 1f;
}
else
{
fade -= Time.deltaTime / starsFadeOutTime;
if (fade < 0f) fade = 0f;
}
tintColor.a = fade;
rend.material.SetColor("_TintColor",tintColor);
//test
//test
}
private float HMS_to_Time(float hour,float second)
{
return 3600 * hour + 60 * minute + second;
}
private bool Time_Falls_Between(float currentTime,float endTime)
{
if (startTime < endTime)
{
if (currentTime >= startTime && currentTime <= endTime) return true;
else return false;
}
else
{
if (currentTime < startTime && currentTime > endTime) return false;
else return true;
}
}
}
我的第一个想法是匹配它们的值,这样它们在任何时候都具有完全相同的值,但这是行不通的,因为火焰似乎在游戏开始几秒钟后就关闭了,并且永远不会再打开。
所以下一个想法是在 DayNightController 脚本中引用 TimeTickSystem 的“timeofDay”并将其设置为始终为“时间”,并在 DayNightController 中调用 TimeTickSystem 的“public void TestTimeEventsOnSetTime()”,但我不知道如何编码这个。
任何建议将不胜感激,因为我已经尝试了至少 10 个小时,但我不知道如何去做。我的编码知识太有限了,尽管我试图将它们的值设置为相同,但我无法让火在夜间点亮并在早晨熄灭。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)