Как сделать универсальную корутину для запуска какой то функции через определённое время?
Ну, чтобы это выглядело как то так
StartCoroutine(WaitAndRun(3f,RunningMethod));
IEnumerator WaitAndRun(float time, out void RunningMethod(int i, int j)
{
yield return new WaitForSeconds(time);
RunningMethod(i,j);
}
void RunningMethod(int i, int j)
{
}
Ну т.е. мы и так можем просто запустить с задержкой через корутину что то, но как это сделать универсальным? Аналог юнитевского
Invoke("RunningMethod", 3f)
Но с возможностью указывать метод прямо,а не через string и возможностью передавать аргументы.
Ну раз надо для 2 переменных, вот 2 варианта
Основа
void RunningMethod(int i, int j)
{
}
1 способ вызова:
System.Action<int, int> runningMethod;
private void Awake()
{
runningMethod = RunningMethod;
}
void Example()
{
DeferredRun(runningMethod, 5, 6, 2f);
}
2.способ вызова:
void Example()
{
DeferredRun(RunningMethod, 5, 6, 2f);
}
Разница в том, что во втором случае при каждом вызове будет создавать новый делегат из метода RunningMethod, а в первом закешировали сразу.
I вариант:
void DeferredRun<T,U>(System.Action<T, U> func, T a,U b, float timer = 0f)
{
StartCoroutine(WaitAndRun(timer, ()=> { func(a, b); }));
}
IEnumerator WaitAndRun(float time, System.Action func)
{
if(time<=0f)
{
if (func != null) func();
yield break;
}
yield return new WaitForSeconds(time);
if(func!=null) func();
}
II вариант:
void DeferredRun<T, U>(System.Action<T, U> func, T a, U b, float timer = 0f)
{
StartCoroutine(WaitAndRun(timer, a, b, func));
}
IEnumerator WaitAndRun<T,U>(float time, T a, U b, System.Action<T, U> func)
{
if (time <= 0f)
{
if (func != null) func(a, b);
yield break;
}
yield return new WaitForSeconds(time);
if (func != null) func(a, b);
}
В первом варианте создает лямбда-функция с замыканием(выделение памяти при каждом вызове), зато корутина более гибкой становится, в первом варианте более быстрый и ограничен 2мя параметрами.
p.s. Не стоит еще забывать, что корутина не работает на выключенных объектах и если запустить корутину на включенном, а потом выключить объект, то корутина остановится на всегда( у invoke нет такой проблемы). Поэтому тут либо надо контролировать включенность объекта(что крайне сложно иногда), либо сделать менеджер, который будет запускать функции других объектов независимо(и если все таки не надо запускать корутину, когда объект выключен, в этом менеджере можно отдельно проверять активность объекта, также можно ждать когда объект снова включится. Придумать условий можно много).
Сборка персонального компьютера от Artline: умный выбор для современных пользователей