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?
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.
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.
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;
}
}
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);
}