0

I've looked around and apparently I've got the choice between these libraries/ solutions:

One:

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

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

Two:

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

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

I want to know if there is any other better way?

Peter O.
  • 32,158
  • 14
  • 82
  • 96
Foskill
  • 81
  • 1
  • 9
  • @SriramSakthivel Can't use `await` with Unity3D due to requirement of .NET 3.5 –  Nov 25 '15 at 09:00
  • @Micky Always feel both written not so good Code looks very messy. – Foskill Nov 25 '15 at 09:10
  • 2
    (Agreed. I've never been a fan of either sadly). The only other method I can think of is old-school take note of the time at start; then in your `Update()` method check for elapsed time. You essentially do everything yourself. Though way more verbose than the above examples, it's type-safe and does not require any extra threads or thread job objects –  Nov 25 '15 at 09:30
  • 1
    yeap, @Micky 's right, that would be your only option – Nika Kasradze Nov 25 '15 at 11:25
  • @Micky Thank you for your answer sincerely. – Foskill Nov 26 '15 at 03:40
  • @NikaKasradze Thank you for your answer sincerely. – Foskill Nov 26 '15 at 03:40
  • @Foskill You are most welcome good sir :) –  Nov 26 '15 at 03:41

1 Answers1

1

This is a summary of my comments above


The only other method I can think of is old-school take note of the time at start; then in your Update() method check for elapsed time. You essentially do everything yourself. Though way more verbose than the above examples, it's type-safe and does not require any extra threads or thread job objects.

Simplest

First we need some fields defined:

private DateTime _start;
private bool _done;

In your start take note of the time:

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

...then in your update check to see how much time has elapsed. If its greater than your timeout of say 2 seconds, fire off what-ever you wish to do - in this case print():

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

That's it.

Re-usable Code

You'll probably find that there are many places where there is a need for this so wouldn't it be groovy if there was a way to cut down on repeated code. Perhaps a class to wrap it up in?

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;
    }
}

Then you could do something like this:

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

...after updating your Update() accordingly:

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

Multiple Jobs

It's just a matter of placing them in a collection and processing it at runtime.

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!"))
            };
}

...a few alterations to 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);    
}