[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.

7 Answers

7

you can Invoke a method after a delay like this

 Invoke("DoSomething", 2);//this will happen after 2 seconds

This freezes my Unity.

if you put a function after invoke it will be executed immediately , why you say it freezes

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 @Muskar said – This isn't the answer the OP was looking for, but it's definitely what I was looking for!

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][1]. [1]: http://unity3d.com/learn/tutorials/modules/intermediate/scripting/coroutines

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.

Why it has to be so extremely complicated? Why I can't simply write a code like this: position.x = 1; transform.position = position; WaitForSeconds(2); position.x += 1; transform.position = position; I tried to move the sprite twice using StartCoroutine(ExecuteAfterTime(1)); StartCoroutine(ExecuteAfterTime(1)); but it doesn't work. It only moves the sprite once. What do I have to do? Do I have make a new function "AnotherExecuteAfterTime"? Why should the users be puzzled with sophisticated concepts like "Yield" and "Coroutine" when they only want to do a "delay(2)" ?

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

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

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.

If all other comments don’t help you, then use this. Maybe it’s not good to write like that…But I don’t care :slight_smile:

void AddSomePassive()
    {
        counter++;
        if (counter == 10)
        {
            ItemsUpdate();
            count = count + dps;
            counttmp = count;
        }
        else if (counter > 10) counter = 0;
    }

Check this. That was a clue for me :smiley: