- Home /
how to make System.Action invoking?
it is in a static class so I cannot use mono invoke.
using System;
// ...
public static void Invoke (){
Action t = Test;
t.Invoke();
}
private static void Test(){
Debug.Log("WORKS");
}
}
this seems to invoke the function immediately.
how would I make it invoke repeating OR how would I make it invoke after a certain time?
thanks in advance.
Invokes are bound to Components. There is no way to do them outside of a Component.
You can however replicate the behaviour using a thread.
thread?
you mean puting an function in to update and checking time all the time or?
No, I mean a thread. They're a common concept so look it up.
Answer by ArkaneX · Feb 10, 2014 at 04:07 PM
It is possible to introduce a delay using threads (as Benproductions1 stated), but the real question is what do you want to do inside the method you want to invoke. It will be executed on another thread, so no Unity specific stuff will be allowed (no GUI, no Instantiate, etc.)
For example, the following code works:
public static void Invoke(int delay)
{
Debug.Log("Started...");
Action t = Test;
Action delayAction = () => Thread.Sleep(delay);
delayAction.BeginInvoke(iar => t(), null);
}
private static void Test()
{
Debug.Log("WORKS");
}
But if you add UnityEngine.GameObject.CreatePrimitive(PrimitiveType.Cube)
to the Test
method, it will fail. That's because Test
method will not be running on main thread. So if you want something like this, you have to look for another solution.
Additionally, this won't work in all cases - for example, in Win8 application, you'd have to change this completely, because Thread.Sleep
is not supported.
EDIT: of course you can skip Action t
declaration and just call Test()
instead of t()
...
it says:
error CS0103: The name `Thread' does not exist in the current context
ok got it it's:
System.Threading.Thread.Sleep(delay);
and still there's a problem because it's not later but it calls it imediatelly.
ALSO I found no iar but suggestion puted me something else as iar:
delayAction.BeginInvoke(IAsyncResult => t(), null);
OH found it works it's just it's not in seconds but 1k = 1 sec, ...
First "Thread.Sleep" uses milliseconds, not seconds, so you might have a too small value. Second Thread.Sleep frezes the thread for that time. Since Unity only uses one thread and the Unity API is not thread-safe it doesn't make much sense to call Sleep ;)
@Bunny83 - using BeginInvoke causes action to be run in another thread, so Thread.Sleep works as expected here - there's no blocking of main thread. Of course code executed at the completion of delayAction is ran on the same thread, and that's why it will work for non Unity specific purposes only. As noted in the answer :)
@sdgd - iar is just a variable name passed to lambda expression, and you can use any valid name you wish there. I used iar, because it's a shortcut from IAsyncResult.
oh @ArkaneX I thought it's logical I don't have a clue about this waters, ... because I asked a question, ...
usually before I ask I dig around 1 hour to 2 days before I ask something as many times I find a solution in that time, ... if it doesn't confusion drive me mad, first, ... and I start :headwall: ing, ...
Answer by Bunny83 · Feb 13, 2014 at 10:01 AM
If your class is still inside a Unity project you can use a coroutine like this:
IEnumerator _InvokeDelegate(System.Action aAction, float aDelay)
{
yield return new WaitForSeconds(aDelay)
aAction();
}
public void InvokeDelegate(System.Action aAction, float aDelay)
{
StartCoroutine(_InvokeDelegate(aAction, aDelay));
}
And finally invoke it like this:
Action t = Test;
InvokeDelegate(t,3); // invoke in 3 seconds
If another non MonoBehaviour class should be able to use this, make the MonoBehaviour which contains the coroutine a singleton.
edit I finally put my CoroutineHelper package on the wiki (the polishing took hours :D). It provides several quite useful methods to run a delegate different ways.
Here's the example scene that's included in the package. This whole example just uses the Start method of one script and everything else is created within the method itself using closures and my coroutine helper pack.
sadly no I can't as I'm using static class.
and if I'd be using mono it's be simpler if I'd be using invoke no?