- Home /
Workaround for using invoke for methods with parameters
private void fooMethod(bool foo = false)
{
Debug.Log(foo);
}
This is the code and the notification I get is
Trying to Invoke method: BlackScreenManager.a couldn't be called.
So I understand invoke can't be used with methods with parameters. But I also set a default value false if the method is being called without any parameters given. So question: How can I workaround this without creating additional methods which just call the method with the parameter?
Answer by HarshadK · Feb 09, 2015 at 09:13 AM
Since you can not call Invoke with parameters you can use StartCoroutine for this.
Say your code is:
void Start()
{
Invoke("MyFunction", 1f);
}
void MyFunction()
{
// Do your thing.
}
Instead you can use Coroutine by passing argument like:
void Start()
{
StartCoroutine(MyFunction(false, 1f));
}
IEnumerator MyFunction(bool status, float delayTime)
{
yield return new WaitForSeconds(delayTime);
// Now do your thing here
}
Good answer.
Although it seems you are mixing up the two different StartCoroutines:
StartCoroutine($$anonymous$$yFunction(false), 1f);
The coroutine which takes an IEnumerator as a parameter only takes one parameter. The 1f value should probably be used as a parameter for the $$anonymous$$yFunction to specify a custom delay? =)
Oops! Just did a copy paste from Invoke and replaced Invoke with StartCoroutine but forgot to make other change. Thanks for pointing it out. Edited answer to reflect the same.
Can you also call StartCoroutine on a function that does not return IEnumerator?
Answer by Heroesflorian · Jul 08, 2017 at 04:45 PM
One other option, for the sake of completeness, could be using global variables instead of method parameters. You can set those accordingly, then invoke a method that makes use of them... depending on your needs and context, this could be feasible or not, but either way it cannot hurt to be aware of the option.
public class Foo : MonoBehaviour {
private int x;
void Start () {
x = Random.Range(0, 100);
Invoke("FooBar", 5.0f);
}
private void FooBar () {
if (x == 0) {
return;
}
for (int i = 0; i < x; i++) {
Debug.Log(i);
}
}
}
This is proppably the easiest way of doing it in small scripts and it's also not that much messy. Thanks a lot buddy!
Answer by JacobGames · Feb 18, 2016 at 11:40 AM
@MapuHoB we had this problem too.
To solve it we made an asset that can help you delay method with parameters in one line of code.
It's called Super Invoke, it's like a more powerful Invoke.
Using Super Invoke your code would be:
float delay = 1f;
SuperInvoke.Run( ()=> fooMethod(true), delay);
You can also create sequences with method and delays that can help you implement complex situations in a simple and fast way.
I've allowed you two (paid) advert posts. No more beyond this please.
There are places on the forum designated for getting your product out there.
Thank you. Just wanted to help others. I wasn't perfectly sure if I could provide it through here.
Its fine :) You have been very reasonable with your posting. A lot of people just spam their ad on every tenuously related link, which just constitutes spam.
Respect+ to you.
Answer by sarahnorthway · Aug 21, 2016 at 08:12 PM
You can use a coroutine to WaitForSeconds, then delegates to pass arbitrary parameters to it. I use this in a static Utils class, but you could also wrap it as an extension method to insert it right into MonoBehavior.
/// <summary>
/// Like MonoBehavior.Invoke("FunctionName", 2f); but can include params. Usage:
/// Utils.RunLater( ()=> FunctionName(true, Vector.one, "or whatever parameters you want"), 2f);
/// </summary>
public static void RunLater(System.Action method, float waitSeconds) {
if (waitSeconds < 0 || method == null) {
return;
}
[SOME_MONOBEHAVIOR].StartCoroutine(RunLaterCoroutine(method, waitSeconds));
}
public static IEnumerator RunLaterCoroutine(System.Action method, float waitSeconds) {
yield return new WaitForSeconds(waitSeconds);
method();
}
Answer by shangkeyun · Sep 11, 2018 at 08:02 AM
Creating extension methods is also an option.
namespace UnityEngine
{
public static class MonoBehaviourExtension
{
public static Coroutine StartCoroutine(this MonoBehaviour behaviour, System.Action action, float delay)
{
return behaviour.StartCoroutine(WaitAndDo(delay, action));
}
private static IEnumerator WaitAndDo(float time, System.Action action)
{
yield return new WaitForSeconds(time);
action();
}
}
}
You can call it like this.
this.StartCoroutine(() =>
{
other.gameObject.SetActive(false);
}, this.delay);
Your answer
Follow this Question
Related Questions
HELP BCE0077: It is not possible to invoke an expression of type 'UnityEngine.Vector3'. 1 Answer
Invoke.Repeating doesn't really "care" about repeat time? 1 Answer
Invoke other script's function 1 Answer
Invoking methods cross-class with arguments 1 Answer
I have no idea why this isnt working 1 Answer