Объединить делегатов для запуска последовательно, а не одновременно? - PullRequest
0 голосов
/ 21 декабря 2018

Я столкнулся с интересной проблемой, для которой мне трудно найти решение.

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

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

Но у меня возникают проблемы с определением необходимого кода для него.

Пример:

public static void RunDelayed([NotNull] Action action, int delay)
{
    if (action == null)
        throw new ArgumentNullException(nameof(action));

    if (delay <= 0)
        throw new ArgumentOutOfRangeException(nameof(delay));

    // 1. expected usage, action will run at next editor update
    EditorApplication.delayCall += () => { action(); };

    // 2. wanted usage, be able to delay it by N times, here by 3 times
    // as you can see, to delay by 3 times you have to build a chain of calls
    // which while simple, the number of delays are hard-coded by the amount of times
    // you pasted EditorApplication.delayCall += () =>

    EditorApplication.delayCall += () =>
        EditorApplication.delayCall += () =>
            EditorApplication.delayCall += () => { action(); };

    // 3. how can the statement above (no. 2) be modeled in a for loop instead ?
    for (var i = 0; i < delay; i++)
    {
        // here I want to do away with manually chaining
        // EditorApplication.delayCall += () => ... statements
        // in turn it allows me to delay by arbitrary N updates
    }
}

Вопрос:

Возможно ли создание такого делегата, если да, то как?

Ссылки:

https://docs.unity3d.com/ScriptReference/EditorApplication-delayCall.html

1 Ответ

0 голосов
/ 21 декабря 2018
EditorApplication.delayCall += DelayCall.ByNumberOfEditorFrames(4, () => print("Foo"));

Реализация:

public static class DelayCall
{
    public static EditorApplication.CallbackFunction ByNumberOfEditorFrames(int n, Action a)
    {
        EditorApplication.CallbackFunction callback = null;

        callback = new EditorApplication.CallbackFunction(() =>
        {
            if (n-- <= 0)
            {
                a();
            }
            else
            {
                EditorApplication.delayCall += callback;
            }
        });

        return callback;
    }
}

Как это работает:

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...