#c# #unity3d
#c# #unity3d
Вопрос:
Итак, на днях я написал сценарий цикла день-ночь, и у меня работает цикл солнце / луна (это действительно грубый сценарий, пока не идеальный), но одна из других вещей, которые я хотел сделать, это иметь возможность вычислять текущее время внутри игры, отрабатывая этот цикл день / ночь.
У меня есть бегущая строка, которая работает до сих пор, но она некорректно масштабируется в процентах от дня.
Может ли кто-нибудь помочь мне с этим, потому что я думаю, что это выходит за рамки моих навыков в математике прямо сейчас.
По сути, я просто хочу определить текущее время суток относительно процента, который мы проходим через цикл день / ночь.
using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
public class DayNightCycle : MonoBehaviour
{
public static DayNightCycle instance;
public Light sun, moon;
public float secondsInFullDay = 3600f;
[Range(0, 1)]
public float currentTimeOfDay = 0f;
[HideInInspector]
public float timeMultiplier = 1f;
float sunInitialIntensity;
public Camera mainCam;
public Material skyboxDay, skyBoxNight;
public float gameTime;
public float fSeconds;
public int totalSeconds, iSeconds, minutes, hours, days;
public int currentSecond, currentMinute, currentHour, currentDay;
public float previousTime;
private void Awake()
{
instance = this;
}
// Start is called before the first frame update
void Start()
{
sunInitialIntensity = sun.intensity;
}
// Update is called once per frame
void Update()
{
UpdateSun();
currentTimeOfDay = (Time.deltaTime / secondsInFullDay) * timeMultiplier;
if (currentTimeOfDay >= 1)
{
currentTimeOfDay = 0;
}
gameTime = Time.deltaTime;
// seconds / total seconds = percentage
// percentage * seconds = total seconds
// seconds = total seconds * percentage
totalSeconds = (int)gameTime;
fSeconds = (secondsInFullDay * currentTimeOfDay);
currentSecond = (int)fSeconds;
if (currentSecond >= 60)
IncrementMinutes();
if (currentMinute >= 60)
IncrementHours();
if (currentHour >= 24)
IncrementDays();
previousTime = (int)gameTime;
}
void UpdateSun()
{
sun.transform.localRotation = Quaternion.Euler((currentTimeOfDay * 360f) - 90, 170, 0);
moon.transform.localRotation = Quaternion.Euler((currentTimeOfDay * 360f) - 90, 170, 0);
float intensityMultiplier = 1f;
float moonIntensityMult = 0.025f;
if (currentTimeOfDay <= 0.23f || currentTimeOfDay >= 0.75f)
{
RenderSettings.skybox = skyBoxNight;
intensityMultiplier = 0f;
moonIntensityMult = 0.025f;
}
else if (currentTimeOfDay <= 0.25f)
{
RenderSettings.skybox = skyBoxNight;
intensityMultiplier = Mathf.Clamp01((currentTimeOfDay - 0.23f) * (1 / 0.02f));
moonIntensityMult = 0f;
}
else if (currentTimeOfDay >= 0.73f)
{
RenderSettings.skybox = skyboxDay;
intensityMultiplier = Mathf.Clamp01(1 - ((currentTimeOfDay - 0.73f) * (1 / 0.02f)));
moonIntensityMult = 0f;
}
sun.intensity = sunInitialIntensity * intensityMultiplier;
moon.intensity = moonIntensityMu<
}
public float GetTimeOfDayInSeconds
{
get { return currentTimeOfDay; }
set { return; }
}
void IncrementMinutes()
{
currentMinute ;
currentSecond = 0;
}
void IncrementHours()
{
currentHour ;
currentSecond = 0;
currentMinute = 0;
}
void IncrementDays()
{
currentDay ;
currentSecond = 0;
currentMinute = 0;
currentHour = 0;
}
}
Комментарии:
1. Я прошу прощения за все дополнительные неиспользуемые переменные, они являются остатками каждого раза, когда я пытался повторить решение своей проблемы. Обычно я выписываю кучу кода, а затем возвращаюсь и пытаюсь упорядочить его позже.
Ответ №1:
Я думаю, что отслеживание секунды, минуты и приращения каждого отдельно — неправильный подход. Теперь вам нужно установить масштаб или коэффициент пропорциональности между вашим игровым временем и реальным временем и обрабатывать сразу одну временную переменную.
Найдите эту пробную функцию, чтобы получить заданное время, которое, я думаю, вам нужно.
using System;
using UnityEngine;
public class DayNightCycle : MonoBehaviour {
// This is public to check with manual input if the obtained time is the one we expect.
// In the real method, this should not exist and should be calculated with the elapsed time of the game,
// commented belowin the getGameTime(int secodsDayDurationInGame) method
public double elapsedRealTime;
float startingGameTime;
DateTime startingGameDate;
private void Start() {
startingGameTime = Time.time;
startingGameDate = DateTime.Now; // choose the starting date you like
}
private float secondsOfARealDay = 24 * 60 * 60;
DateTime getGameTime(int secodsDayDurationInGame) {
float scaledElapsedSecondInGame = secondsOfARealDay / secodsDayDurationInGame; // second equivalent in your game
//float elapsedRealTime = Time.time - startingGameTime; // uncomment to calculate with elapsed real time.
DateTime gateDateTime = startingGameDate.AddSeconds(elapsedRealTime * scaledElapsedSecondInGame);
return gateDateTime;
}
void OnMouseDown() { // this makes the cube clickable
Debug.LogError(getGameTime(3600).ToString());
}
}
Вы можете попробовать сделать куб интерактивным для печати выходных данных при обновлении прошедшего времени в общедоступной переменной.
Это для 3600 второго дня в вашей игре, но если вы хотите другую продолжительность игрового дня, вы можете просто настроить этот параметр и попробовать.
Важно иметь коллайдер, в противном случае cube не будет доступен для просмотра. Однако оно добавляется по умолчанию, когда вы добавляете примитивный щелчок правой кнопкой мыши в сцене -> 3D-объект -> Куб.
Вы можете проверить, например, что если вы добавите 3600 к общедоступной переменной истекшего времени и щелкнете по кубу, вы получите завтрашнюю дату в консоли.
Когда вы убедитесь, что функция работает в соответствии с вашими потребностями, вы можете раскомментировать строку //float elapsedRealTime = Time.time - startingGameTime;
, чтобы использовать прошедшее реальное время или то, которое вы хотите для вычисления даты.
Комментарии:
1. Это интересный способ добиться этого.
2. Итак, это помогает мне правильно вычислить игровое время, которое кажется пропорциональным. Проблема в том, что, поскольку я играю в 5: 30 вечера, он начинается в 5: 30 вечера, когда он должен быть запущен в 00: 01.
3. Я думаю, что я только что получил это, работая с вашей моделью! Неважно, что это вычисление полного дня прошло до того, как цикл солнца / луны изменился с 0 на 1.
Ответ №2:
Хорошо, итак, я добрался до того, что теперь оно правильно синхронизировано с циклом день / ночь, мне просто нужно немного почистить этот код. Примечание: Способ, которым я увеличиваю количество дней, начнет давать сбои, если вы используете исключительно длинный игровой день, я думаю. Логическое значение может сработать, но оно также может дать вам новый день до конца текущего дня. Я тестировал это в течение 3600 секунд в день.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
public class DayNightCycle : MonoBehaviour
{
public static DayNightCycle instance;
public Light sun, moon;
public float secondsInFullDay = 3600f;
[Range(0, 1)]
public float currentTimeOfDay = 0f;
[HideInInspector]
public float timeMultiplier = 1f;
float sunInitialIntensity;
public Material skyboxDay, skyBoxNight;
public double elapsedRealTime;
public float secondsPerDayMultiplier;
[SerializeField]
private float speedOfGameSecond, speedOfGameMinute, speedOfGameHour, speedOfGameDay;
[SerializeField]
private float currentGameSecond, currentGameMinute, currentGameHour, currentGameDay;
private bool stopIncrementingDay;
private void Awake()
{
instance = this;
}
// Start is called before the first frame update
void Start()
{
speedOfGameSecond = secondsInFullDay / 24 / 60 / 60;
speedOfGameMinute = secondsInFullDay / 24 / 60;
speedOfGameHour = secondsInFullDay / 24;
speedOfGameDay = secondsInFullDay;
sunInitialIntensity = sun.intensity;
}
// Update is called once per frame
void Update()
{
UpdateSun();
currentTimeOfDay = (Time.deltaTime / secondsInFullDay) * timeMultiplier;
if (currentTimeOfDay >= 1)
{
currentTimeOfDay = 0;
}
secondsPerDayMultiplier = currentTimeOfDay * secondsInFullDay;
// seconds / total seconds = percentage
// percentage * seconds = total seconds
// seconds = total seconds * percentage
currentGameSecond = secondsPerDayMultiplier / speedOfGameSecond;
currentGameMinute = secondsPerDayMultiplier / speedOfGameMinute;
currentGameHour = secondsPerDayMultiplier / speedOfGameHour;
if(!stopIncrementingDay amp;amp; currentGameHour >= 23.999)
{
IncrementDay();
stopIncrementingDay = true;
} else if(currentGameHour <= 23.999)
{
stopIncrementingDay = false;
}
elapsedRealTime = Time.deltaTime;
previousTime = Time.deltaTime;
}
void UpdateSun()
{
sun.transform.localRotation = Quaternion.Euler((currentTimeOfDay * 360f) - 90, 170, 0);
moon.transform.localRotation = Quaternion.Euler((currentTimeOfDay * 360f) - 90, 170, 0);
float intensityMultiplier = 1f;
float moonIntensityMult = 0.025f;
if (currentTimeOfDay <= 0.23f || currentTimeOfDay >= 0.85f)
{
RenderSettings.skybox = skyBoxNight;
intensityMultiplier = 0f;
moonIntensityMult = 0.025f;
}
else if (currentTimeOfDay <= 0.25f)
{
RenderSettings.skybox = skyBoxNight;
intensityMultiplier = Mathf.Clamp01((currentTimeOfDay - 0.23f) * (1 / 0.02f));
moonIntensityMult = 0f;
}
else if (currentTimeOfDay >= 0.83f)
{
RenderSettings.skybox = skyboxDay;
intensityMultiplier = Mathf.Clamp01(1 - ((currentTimeOfDay - 0.83f) * (1 / 0.02f)));
moonIntensityMult = 0f;
}
sun.intensity = sunInitialIntensity * intensityMultiplier;
moon.intensity = moonIntensityMu<
}
public float GetTimeOfDayPercent
{
get { return currentTimeOfDay; }
set { return; }
}
public float GetSecondsPerDay()
{
return secondsInFullDay;
}
private void IncrementDay()
{
currentGameSecond = 0;
currentGameMinute = 0;
currentGameHour = 0;
currentGameDay ;
}
public void GetTimeOfDay()
{
// now to work on this
}
}