Какими способами можно контролировать задержку в Unity?

Я осмотрелся и, видимо, у меня есть выбор между этими библиотеками/решениями:

Один:

public void Awake() {
    Invoke("InvokeAndPrint", 2);
}

void InvokeAndPrint() {
    print("InvokeAndPrint 2");
}

Два:

void Start() {
    StartCoroutine(WaitAndPrint(2.0F));
}

IEnumerator WaitAndPrint(float waitTime) {
    yield return new WaitForSeconds(waitTime);
    print("WaitAndPrint " + Time.time);
}

Я хочу знать, есть ли другой лучший способ?


person Foskill    schedule 25.11.2015    source источник
comment
@SriramSakthivel Невозможно использовать await с Unity3D из-за требований .NET 3.5   -  person MickyD    schedule 25.11.2015
comment
@Micky Всегда чувствую, что оба написаны не так хорошо. Код выглядит очень грязно.   -  person Foskill    schedule 25.11.2015
comment
(Согласен. К сожалению, я никогда не был поклонником ни того, ни другого). Единственный другой метод, который я могу придумать, - это старая школа, учитывающая время при запуске; затем в вашем методе Update() проверьте прошедшее время. Вы по сути все делаете сами. Хотя он намного более подробный, чем приведенные выше примеры, он типобезопасен и не требует дополнительных потоков или объектов задания потока.   -  person MickyD    schedule 25.11.2015
comment
да, @Micky прав, это был бы твой единственный вариант   -  person Nika Kasradze    schedule 25.11.2015
comment
@Micky Спасибо за ваш ответ искренне.   -  person Foskill    schedule 26.11.2015
comment
@NikaKasradze Искренне благодарю вас за ответ.   -  person Foskill    schedule 26.11.2015
comment
@Foskill Добро пожаловать, сэр :)   -  person MickyD    schedule 26.11.2015


Ответы (1)



Это краткое изложение моих комментариев выше


Единственный другой метод, который я могу придумать, - это старая школа, учитывающая время при запуске; затем в вашем методе Update() проверьте прошедшее время. Вы по сути все делаете сами. Хотя он и более подробный, чем приведенные выше примеры, он типобезопасен и не требует дополнительных потоков или объектов задания потока.

Самый простой

Сначала нам нужно определить некоторые поля:

private DateTime _start;
private bool _done;

В начале обратите внимание на время:

void Start()
{
    _start = DateTime.Now;
}

... затем в вашем обновлении проверьте, сколько времени прошло. Если это больше, чем ваше время ожидания, скажем, 2 секунды, запустите все, что вы хотите сделать - в этом случае print():

void Update()
{
    if (! _done && (DateTime.Now - _start).TotalSeconds >= 2)
    {
        print("hello world");
        _done = true;
    }
}

Вот и все.

Повторно используемый код

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

class DelayedJob
{
    private readonly TimeSpan _delay;
    private readonly Action _action;
    private readonly DateTime _start;

    public DelayedJob(TimeSpan delay, Action action)
    {
        if (action == null)
        {
            throw new ArgumentNullException("action");
        }
        _delay = delay;
        _action = action;
        _start = DateTime.Now;
    }

    /// <summary>
    /// Updates this instance.
    /// </summary>
    /// <returns>true if there is more work to do, false otherwise</returns>
    public bool Update()
    {
        if (DateTime.Now - _start >= _delay)
        {
            _action();
            return false;
        }

        return true;
    }
}

Тогда вы можете сделать что-то вроде этого:

void Start()
{
    _job = new DelayedJob(TimeSpan.FromSeconds(2), ()=> print("hello"));
}

...после обновления вашего Update() соответственно:

void Update()
{
    if (_job != null && !_job.Update())
    {
        _job = null;
    }
}

Несколько заданий

Нужно просто поместить их в коллекцию и обработать во время выполнения.

private List<DelayedJob> _jobs; 

void Start()
{
    _jobs = new List<DelayedJob>
            {
                new DelayedJob(TimeSpan.FromSeconds(2), () => print("star wars")),
                new DelayedJob(TimeSpan.FromSeconds(3f), () => print("is coming!"))
            };
}

...несколько изменений в Update():

void Update()
{    
    bool again;

    do
    {
        again = false;
        // you probably want to optimise this so that we don't check the same items
        // at the start again after removing an item
        foreach (var delayedJob in _jobs)
        {
            if (!delayedJob.Update())
            {
                _jobs.Remove(delayedJob);
                again = true; // start over
                break;
            }
        }
    }
    while (again);    
}
person MickyD    schedule 26.11.2015
comment
Вот что я хочу ответить Спасибо еще раз! - person Foskill; 26.11.2015
comment
@Foskill Не беспокойся, приятель, и тебе тоже спасибо. Я должен был записать это в первую очередь. Счастливого единства :) - person MickyD; 26.11.2015
comment
Ха, счастливого единства тоже :) - person Foskill; 26.11.2015