Таймеры в Unity

1160
21 декабря 2016, 01:24

Мне в одном классе нужно реализовать два таймера: первый бесконечно (или пока сцена с игрой не будет закрыто) должен каждые m секунд выполнять действие (1), второй каждые n секунд действие (2). Нужно учитывать то, что есть в игре пауза, и при её вызове нужно таймеры на паузу ставить (я бы мог сделать через корутины, но не знаю как их ставить на паузу). Как это можно реализовать?

Answer 1

Самый банальный способ это иметь флаг, который устанавливается true/false когда игра активна/на паузе. В зависимости от этого флага уже танцевать в корутине.

Как пример:

using UnityEngine;
using System.Collections;
public class TimerTest : MonoBehaviour {
    public bool isGameStopped = false;
    private int timer = 0;
    IEnumerator WaitAndPrint() {        
        while(true) {       
            if (!isGameStopped) {
                Debug.Log("TimerCount: " + (timer++));
                yield return new WaitForSeconds(1);             
            }
            yield return null;
        }
    }
    void Start() {  
        StartCoroutine(WaitAndPrint());     
    }
}

Естественно isGameStopped скорее всего будет не в самом этом классе. Но это уже вам решать где его делать и в какой момент и каким способом его менять.

Смысл тут в том, что если флаг false, то будет простой банальный выход из корутины yield return null;. В ином же случае будет заход в if (!isGameStopped) и срабатывание счетчика.

Еще вариант - стартовать и останавливать корутину при возникновении какого-либо события (паузы)

using UnityEngine;
using System.Collections;
public class TimerTest : MonoBehaviour {
    public bool isGameStopped = false;
    private int timer = 0;
    private IEnumerator coroutine;
    IEnumerator WaitAndPrint() {        
        while(true) {                       
            Debug.Log("TimerCount: " + (timer++));
            yield return new WaitForSeconds(1);                             
        }
    }

    void Start() {      
        coroutine = WaitAndPrint();
    }

    void Update() {
        if (Input.GetMouseButtonDown(0))
             StartCoroutine(coroutine);
         if (Input.GetKeyDown("space")){
            StopCoroutine(coroutine);
        }
    }
}

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

Для float

using UnityEngine;
using System.Collections;
public class TimerTest : MonoBehaviour {
    public bool isGameStopped = false;
    private float timer = 0.0f;
    private float timeDelta = 0.0f;
    private IEnumerator coroutine;
    IEnumerator WaitAndPrint() {        
        while(true) {                               
            timer = Time.time - timeDelta;          
            yield return null;
        }
    }
    void Start() {          
        coroutine = WaitAndPrint();
        StartCoroutine(coroutine);
    }

    void Update() {
        if (Input.GetMouseButtonDown(0)) {
            timeDelta = Time.time - timer;
            StartCoroutine(coroutine);           
        }
         if (Input.GetKeyDown("space")){
            StopCoroutine(coroutine);            
            timeDelta = 0;
        }
    }
}

Time.time - время с начала игры. timeDelta - вычисляется когда запускается корутина, и обнуляется, когда останавливается.

Вообще, зависит от того, каким образом происходит пауза в игре.

Например, в некоторых случаях программисты делают паузу делая значение глобального времени Time.timeScale равным нулю. Тогда всё останавливается. В том числе и время Time.time. Если Time.timeScale равно единице, то это полная игровая скорость.

Соответственно, если пауза делается именно через timeScale, то, в принципе, достаточно отслеживать Time.time, который будет показывать нужное время. А если пауза делается другими способами, но Time.time неизменно течет, то тогда делать примерно как описано в коде выше.

READ ALSO
Работа с двумя формами. Передача Label между формами

Работа с двумя формами. Передача Label между формами

Добрый день! У меня есть две формы PZ6 и inputForm Вторая вызывается из первой по нажатию кнопки

411
axcryptNet исходники

axcryptNet исходники

Привет, ребят, при использовании библиотек AxcryptNet для шифрования файлов столкнулся с проблемой

376
System.NullReferenceException: Ссылка на объект не указывает на экземпляр объекта

System.NullReferenceException: Ссылка на объект не указывает на экземпляр объекта

Всем приветПишу игру "Сапёр", работающую из окна консоли

657