- Home /
[c#] How can I let something happen after a small delay?
How can I add a small delay between things happening in a function, after the delay it should continue with what it was doing? in C#
it's just Invoke. that's all there is to it. there's also InvokeRepeating if you want it to happen over and over. it's absurd to dabble with coroutines for something so simple.
Answer by dmg0600 · Sep 24, 2014 at 01:44 PM
You can do it with coroutines in any MonoBehaviour:
IEnumerator ExecuteAfterTime(float time)
{
yield return new WaitForSeconds(time);
// Code to execute after the delay
}
You can call it with, for example, StartCoroutine(ExecuteAfterTime(10));
Note that it will execute asynchronous so put everything that has to wait for it to be done, inside the coroutine.
But, when I call it from the update fuction befor the function before doing this will it not be called multiple times?
Call it somewhere else (like Start function). Check the tutorial.
But what if it's done through there? how can I make it so it will only be executed once?
The start function only gets called once (at the beginning of the scene). Check the tutorial, try the code. It doesn't hurt.
If you call it in Update it will be executed once every frame, as if it were a normal method call or an invoke.
If you want to be sure that it does not execute more than once until it finish its execution you can add a boolean flag:
private bool isCoroutineExecuting = false;
IEnumerator ExecuteAfterTime(float time)
{
if (isCoroutineExecuting)
yield break;
isCoroutineExecuting = true;
yield return new WaitForSeconds(time);
// Code to execute after the delay
isCoroutineExecuting = false;
}
This way it will stop the new coroutine if it is still executing a previous one and start if it is not executing it yet.
Answer by 767_2 · Sep 24, 2014 at 01:51 PM
you can Invoke a method after a delay like this
Invoke("DoSomething", 2);//this will happen after 2 seconds
if you put a function after invoke it will be executed immediately , why you say it freezes
"DoSomething" is the name of the function to call. This answer is exactly what I needed, so I upvoted it, even though I know it wasn't the answer the OP was looking for.
Same as what @$$anonymous$$uskar said – This isn't the answer the OP was looking for, but it's definitely what I was looking for!
Answer by UberGeoff · Feb 01, 2018 at 02:08 AM
We can extend this futher by executing an Action after the delay:
IEnumerator ExecuteAfterTime(float time, Action task)
{
if (isCoroutineExecuting)
yield break;
isCoroutineExecuting = true;
yield return new WaitForSeconds(time);
task();
isCoroutineExecuting = false;
}
Then use it like this:
StartCoroutine(ExecuteAfterTime(0.5f, () =>
{
//Add somwthing here
}));
What is the isCoroutineExecuting for? Im not sure if its doing anything
It just makes sure the coroutine isn't already waiting for "time", and breaks if it is. Because most of the time, you don't want multiple instances of the same coroutine running in parallel.
Answer by TomZe · Sep 26, 2018 at 03:47 PM
use this class :
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Linq;
using UnityEngine;
using System;
namespace LateExe {
class Executer
{
object script;
MonoBehaviour mono_script;
public Executer(object script)
{
this.script = script;
this.mono_script = this.script as MonoBehaviour;
}
public InvokeId DelayExecute(float DelayInSeconds, Action<object[]> lambda, params object[] parameters)
{
return new InvokeId( mono_script.StartCoroutine(Delayed(DelayInSeconds, lambda, parameters)));
}
public InvokeId DelayExecute(float DelayInSeconds, string methodName, params object[] parameters)
{
foreach (MethodInfo method in script.GetType().GetMethods())
{
if (method.Name == methodName)
return new InvokeId(mono_script.StartCoroutine(Delayed(DelayInSeconds, method, parameters)));
}
return null;
}
public InvokeId ConditionExecute(Func<bool> condition, string methodName, params object[] parameters)
{
foreach (MethodInfo method in script.GetType().GetMethods())
{
if (method.Name == methodName)
return new InvokeId(mono_script.StartCoroutine(Delayed(condition, method, parameters)));
}
return null;
}
public InvokeId ConditionExecute(Func<bool> condition, Action<object[]> lambda, params object[] parameters)
{
return new InvokeId(mono_script.StartCoroutine(Delayed(condition, lambda, parameters)));
}
public void StopExecute(InvokeId id)
{
mono_script.StopCoroutine(id.coroutine);
}
IEnumerator Delayed(float DelayInSeconds, Action<object[]> lambda, params object[] parameters)
{
yield return new WaitForSeconds(DelayInSeconds);
lambda.Invoke(parameters);
}
IEnumerator Delayed(float DelayInSeconds, MethodInfo method, params object[] parameters)
{
yield return new WaitForSeconds(DelayInSeconds);
method.Invoke(script, parameters);
}
IEnumerator Delayed(Func<bool> condition, Action<object[]> lambda, params object[] parameters)
{
yield return new WaitUntil(condition);
lambda.Invoke(parameters);
}
IEnumerator Delayed(Func<bool> condition, MethodInfo method, params object[] parameters)
{
yield return new WaitUntil(condition);
method.Invoke(script, parameters);
}
}
class InvokeId
{
public readonly Coroutine coroutine;
public InvokeId(Coroutine coroutine)
{
this.coroutine = coroutine;
}
}
}
Examples: execute after 2 seconds in a few ways
using LateExe;
public class Game_Script: MonoBehaviour {
void Awake {
Executer exe = new Executer(this);
exe.DelayExecute(2f , x=> Debug.Log("after 2 seconds"));
exe.DelayExecute(2f , x=> Debug.log(x[0]) , "after 2 seconds + params");
exe.DelayExecute(2f , "after2seconds");
exe.DelayExecute(2f , "afterXseconds", 2);
exe.DelayExecute(2f , "afterXY", 2, " seconds");
}
void after2seconds ()
{
Debug.Log("after 2 seconds");
}
void afterXseconds(int x) {
Debug.log("after" + x + "seconds");
}
void afterXY(int x , string y) {
Debug.log("after " + x + y);
}
}
Example stop:
var id = exe.DelayExecute(0.5f, x => Debug.Log("not gonna run"));
exe.StopExecute(id);
Example when:
exe.ConditionExecute(() => score > 100 , x => Debug.Log("you're good"));
I know this is old but its a very common thing and I hope unity will one day implement such a class into the engine. creating a coroutine every time is not a clean way of doing things.
I like this answer, but, tiny gripe --- should be Executor
-- thanks for this tool btw, just finished implementing and it's very convenient and intuitive
Answer by HarshadK · Sep 24, 2014 at 01:45 PM
Check Coroutines.
It is exactly what you need.
Invoke()
is simpler, but if one wants to call method with parameters, coroutine is apparently a good solution.