Как оптимизировать таймер обратного отсчета? - PullRequest
0 голосов
/ 12 июля 2019

Уважаемое сообщество stackoverflow,

У меня есть таймер обратного отсчета для включения моих двойных очков, и теперь у меня проблема, потому что мой код работает нормально в игре, но когда таймер активен, игра задерживается, не слишком много, но любое отставание не хорошо для моей игры, потому что игрок Нужно играть плавно, без каких-либо неоптимизированных компонентов.

У меня есть этот код, и я держу пари, что игра отстает, потому что код находится в методе обновления (я пытался поместить его в сценарий диспетчера игр, но таймер не начал обратный отсчет, так что это не решение)

Это код (спасибо пользователю stackoverflow @siusiulala, который написал мне рабочий код) но похоже, что он должен быть в другом методе или что-то в этом роде, потому что метод Обновления работает с быстрым обратным отсчетом.

private void Update(){ 
if (isDoublePoints)
        {
            // Countdown the timer with update time
            powerUpTimer -= Time.deltaTime;
            Debug.Log("TIMER ISS " + powerUpTimer);
            if (powerUpTimer <= 0)
            {
                // End of power up time 
                isDoublePoints = false;
            }
        }



    }

    public void OnPickPowerUp(float buffTime)
    {
        powerUpTimer += buffTime;
    }

Я надеюсь, что кто-нибудь даст решение проблемы с лагом, потому что я видел много игр, в которых есть системы включения питания без каких-либо лагов внутри ...

Спасибо stackoverflow, без тебя моя игра никогда бы не завершилась:)

Ответы [ 2 ]

4 голосов
/ 12 июля 2019

По моему опыту, Debug.Log() - это очень дорогой метод.Это вызовет задержку при вызове каждого кадра.Из-за этого моя IDE даже выделяет использование Debug.Log() в Update().Используйте этот метод только для отладки, а затем удалите.

Если вы хотите увидеть значение таймера, добавьте атрибут [SerializeField] в свое поле, и он появится в инспекторе.

Вы можете использовать профилировщик, выбрав Window-Analysis-Profiler , предполагая, что вы используете Unity 2018.x.Он записывает, сколько времени занимает обработка, и помогает найти узкие места.

3 голосов
/ 12 июля 2019

что ответ троллингара говорит о Debug.Log правильно.

Использование [SerializeField] может рассматриваться как грязный и ленивый взлом для некоторыхлюди.Поскольку у него есть побочный эффект, он теперь сериализован , это означает, что значение хранится в активах.Это неплохо, но если вы точны, этого не следует делать с полями, которые все равно будут изменены во время выполнения.

Вместо этого вы можете просто зайти в Инспектор, открыть контекстное меню и установить его на DebugВ режиме

enter image description here

это заставляет Инспектора не использовать пользовательские сценарии EditorScripts, а вместо этого отображать все закрытые поля (типов Serializable).

Например, для компонента Transform

enter image description here


Однако этот способ более эффективен, чем использование метода Update с флагом вообще будет скорее использовать Coroutines.

Сопрограммы можно запускать и запускать параллельно (каждый кадр сразу после) метод Update, но преимущество: когдасопрограмма завершена - она ​​завершена и не продолжает проверять флаг bool каждый кадр.

Поэтому всякий раз, когда вы выбираете PowerUp вместо установки флага на true, лучше использовать

StartCoroutine(PowerUpRoutine());

и реализовать такую ​​подпрограмму, как

private IEnumerator PowerUpRoutine()
{
    isDoublePoints = true;

    while(powerUpTimer > 0)
    {
        // Countdown the timer with update time
        powerUpTimer -= Time.deltaTime;
        //Debug.Log("TIMER ISS " + powerUpTimer);

        // yield in simple words makes Unity "pause"
        // the execution here, render this frame and continue from here
        // in the next frame
        yield return null;
    }

    // End of power up time 
    isDoublePoints = false;
}

public void OnPickPowerUp(float buffTime)
{
    powerUpTimer += buffTime;

    // avoid concurrent routines
    if(!isDoublePoints) StartCoroutine(PowerUpRoutine());
}

В порядкечтобы отобразить его в своей игре, вы можете использовать Text или TextMeshPro и установить текст, например,

[SerializeField] private Text _text;

private IEnumerator PowerUpRoutine()
{
    isDoublePoints = true;

    while(powerUpTimer > 0)
    {
        // Countdown the timer with update time
        powerUpTimer -= Time.deltaTime;
        //Debug.Log("TIMER ISS " + powerUpTimer);

        // set the text of the Text component to display the value
        // for the $ symbol google for "c# string interpolation"
        _text.text = $"TIMER IS {powerUpTimer:00.00}";

        // yield in simple words makes Unity "pause"
        // the execution here, render this frame and continue from here
        // in the next frame
        yield return null;
    }

    // End of power up time 
    isDoublePoints = false;
}
...