Доброго времени суток, уважаемые форумчане Недавно возникла задача, для реализации который необходим был таймер (если быть точным, то обратный отчёт). У каждой задачи есть решение, и эта из числа подобных задач. Поехали.
UniTimer
UPD: Добавлен вариант реализации таймера (более грамотный). Смотреть внизу поста. Предложил Strom54.
Первый вариант.
Всё просто. Создаём класс. Код ниже:
Код
using UnityEngine; using System.Collections;
/// <summary> /// Обратный отсчёт /// </summary> public class UniTimer { private float seconds; private bool isFinished; private bool isEnabled;
/// <summary> /// Единоразовое срабатывание таймера. Возвращает true только один раз, при условие, что время истекло. /// </summary> /// <returns></returns> public bool ElapsedAndShotdown() { if (isEnabled && isFinished) { isEnabled = false; return true; } else return false; }
/// <summary> /// Если время истекло, то возвращает true. /// </summary> /// <returns></returns> public bool Elapsed() { if (isFinished) return true; else return false; } }
Сохранили класс. Теперь пример использования:
Код
using UnityEngine; using System.Collections;
public class TestScript: MonoBehaviour { private UniTimer timer;
void Start() { Debug.Log("Timer started!"); timer = new UniTimer(5); // таймер на 5 секунд }
void Update() { if (timer != null) { timer.Update(); // Не забываем вызывать. Иначе таймер не будет изменяться.
if (timer.ElapsedAndShotdown()) { Debug.Log("Таймер сработал и отключился. Этот код выполнится единожды"); } } }
}
Второй пример использования:
Код
using UnityEngine; using System.Collections;
public class TestScript: MonoBehaviour { private UniTimer timer;
void Start() { Debug.Log("Timer started!"); timer = new UniTimer(5); // таймер на 5 секунд }
void Update() { if (timer != null) { timer.Update(); // Не забываем вызывать. Иначе таймер не будет изменяться.
if (timer.Elapsed()) { Debug.Log("Время таймера истекло. Выполняется, пока вручную не отключить таймер."); } } }
}
Второй вариант.
Простота использования аналогична стандартному таймеру в C# Сначала я хотел реализовать с использованием отдельных потоков, но из-за этого могли возникнуть проблемы, поэтому пришлось делать другим методом. Создаем объект - пустышку и кидаем на него скрипт TimerManager - этот класс производит обновление всех активных таймеров. Стоит учесть, что скрипт делает объект не-уничтожаемым при переходе на другую сцену, так что на каждой сцене не нужно плодить лишних менеджеров, хотя и ошибок это не вызовет.
Ну а теперь дело за малым:
Код
void Start() { SimpleTimer timer = new SimpleTimer(5);//Создаем объект. Вторым необязательным параметром можно указать, запускать ли таймер сразу при создании объекта. timer.OnTimer += new SimpleTimer.SimpleTimerEvent(TimerActivated); // Подписываемся на событие, которое кинет таймер. timer.Start(); // Запускаем таймер. }
void TimerActivated(SimpleTimer timer) { timer.OnTimer -= new SimpleTimer.SimpleTimerEvent(TimerActivated); // Желательно отписаться от события таймера. Хотя сделать это можно где-нибудь еще, например в OnDestroy
Debug.Log("Timer activated !"); }
Сами классы: TimerManager
Код
using UnityEngine;
public class TimerManager : MonoBehaviour { public static TimerManager mgr;
public delegate void TimerManagerEvent(); public event TimerManagerEvent OnUpdate;
Добавлено (25.04.2014, 00:28) --------------------------------------------- Вот мой аналог таймера: Простота использования аналогична стандартному таймеру в C# Сначала я хотел реализовать с использованием отдельных потоков, но из-за этого могли возникнуть проблемы, поэтому пришлось делать другим методом. Создаем объект - пустышку и кидаем на него скрипт TimerManager - этот класс производит обновление всех активных таймеров. Стоит учесть, что скрипт делает объект не-уничтожаемым при переходе на другую сцену, так что на каждой сцене не нужно плодить лишних менеджеров, хотя и ошибок это не вызовет.
Ну а теперь дело за малым:
Код
void Start() { SimpleTimer timer = new SimpleTimer(5);//Создаем объект. Вторым необязательным параметром можно указать, запускать ли таймер сразу при создании объекта. timer.OnTimer += new SimpleTimer.SimpleTimerEvent(TimerActivated); // Подписываемся на событие, которое кинет таймер. timer.Start(); // Запускаем таймер. }
void TimerActivated(SimpleTimer timer) { timer.OnTimer -= new SimpleTimer.SimpleTimerEvent(TimerActivated); // Желательно отписаться от события таймера. Хотя сделать это можно где-нибудь еще, например в OnDestroy
Debug.Log("Timer activated !"); }
Сами классы:
TimerManager
Код
using UnityEngine;
public class TimerManager : MonoBehaviour { public static TimerManager mgr;
public delegate void TimerManagerEvent(); public event TimerManagerEvent OnUpdate;
Хоть тс и написал что знает про корутин, однако можно как то так
Насколько я знаю, если наследовать класс от MonoBehaviour, то работать он будет только в качестве компонента на GameObject'е, в таком случае было бы слишком затратно, скажем, создать пару сотен таймеров.
Сообщение отредактировал Storm54 - Пятница, 25 Апреля 2014, 06:59
Storm54, я просто писал создав скрипт в юнити. А так по сути я просто привел пример как можно сделать таймер. доработать и сделать его отдельным классом тож не составит труда)
Storm54, А какая разница? Повесить его на один пустой ГО. А в коде создаешь новые объекты типа таймер да и все. Хотя конечно спорить прям сильно не буду) Еще раз повторюсь, это просто пример)
Сообщение отредактировал rak - Пятница, 25 Апреля 2014, 07:33
Storm54, спасибо. С удовольствием посмотрел на Вашу реализацию. Изначально тоже была идея создания таймера по аналогии со стандартным таймером c#. Однако не хватило опыта, для реализации подписки на событие. Если не против, я вынесу Ваши классы и пример использования в шапку. Авось ещё кому пригодится.