Unity — Пытается вычислить игровое время

#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
    }
}