Unity Coroutines C#

216
22 апреля 2018, 20:40

Как сделать универсальную корутину для запуска какой то функции через определённое время?

Ну, чтобы это выглядело как то так

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 и возможностью передавать аргументы.

Answer 1

Ну раз надо для 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 нет такой проблемы). Поэтому тут либо надо контролировать включенность объекта(что крайне сложно иногда), либо сделать менеджер, который будет запускать функции других объектов независимо(и если все таки не надо запускать корутину, когда объект выключен, в этом менеджере можно отдельно проверять активность объекта, также можно ждать когда объект снова включится. Придумать условий можно много).

READ ALSO
Смысл помещения DateTime в контейнер

Смысл помещения DateTime в контейнер

В исходном коде одной программы, внутри NinjectModule, я нашёл такую строку:

177
Бегущая пунктирная рамка у блока

Бегущая пунктирная рамка у блока

Как сделать так, чтобы граница блока была не статичной, а бегала по направлению часовой стрелки? Понимаю, что как-то должно быть с помощью...

217
Съезжают элементы при заполнении формы

Съезжают элементы при заполнении формы

Вот какая проблема при отображении сайта на мобильном устройствеЕсть форма обратной связи, после которой идут КОНТАКТЫ, НО, при заполнении...

190
При наведении на пункт меню показывать содержимое соответствующего блока

При наведении на пункт меню показывать содержимое соответствующего блока

Мне нужно чтобы при наведении на пункт меню показывался контент, который соответствует этому пункту но лежит в другом блоке standart-contentИ как...

231