2

All this started yesterday when I use that code for make a snippet:

void Start() {
    print("Starting " + Time.time);
    StartCoroutine(WaitAndPrint(2.0F));
    print("Before WaitAndPrint Finishes " + Time.time);
}
IEnumerator WaitAndPrint(float waitTime) {
    yield return new WaitForSeconds(waitTime);
    print("WaitAndPrint " + Time.time);
}

From: http://docs.unity3d.com/Documentation/ScriptReference/MonoBehaviour.StartCoroutine.html

The problem is that I want to set a static variable from a class of that type:

class example
{
    private static int _var;
    public static int Variable
    {
        get { return _var; }
        set { _var = value; }
    }

}

Which is the problem? The problem is that If put that variable in a parameter of a function this "temporal parameter" will be destroyed at the end of the function... So, I seached a little bit, and I remebered that:

class OutExample
{
    static void Method(out int i)
    {
        i = 44;
    }
    static void Main()
    {
        int value;
        Method(out value);
        // value is now 44
    }
}

From: http://msdn.microsoft.com/es-es/library/ms228503.aspx

But, (there's always a "but"), Iterators cannot have ref or out... so I decide to create my own wait function because Unity doesn't have Sleep function...

So there's my code:

    Debug.Log("Showing text with 1 second of delay.");

    float time = Time.time;

    while(true) {
        if(t < 1) {
            t += Time.deltaTime;
        } else {
            break;
        }
    }

    Debug.Log("Text showed with "+(Time.time-time).ToString()+" seconds of delay.");

What is the problem with that code? The problem is that It's very brute code, becuase It can produce memory leak, bugs and of course, the palayzation of the app...

So, what do you recomend me to do?

Community
  • 1
  • 1
z3nth10n
  • 2,341
  • 2
  • 25
  • 49
  • It seems very likely that you don't want to sleep. That is seldom the solution. What you do want is hard to tell. At least, I cannot understand the question. – David Heffernan Mar 11 '14 at 14:20
  • The problem is that I want to know if there is a alternative, to Thread.Sleep (Game freezes), Tasks (FW4) or Yield return new WaitForSeconds (out and ref aren't compatible with Iterators that are used in this type of returns) – z3nth10n Mar 11 '14 at 15:04

3 Answers3

2

You could do something like this:

void Start()
{
    print( "Starting " + Time.time );
    StartCoroutine( WaitPrintAndSetValue( 2.0F, theNewValue => example.Variable = theNewValue ) );
    print( "Before WaitAndPrint Finishes " + Time.time );
}

/// <summary>Wait for the specified delay, then set some integer value to 42</summary>
IEnumerator WaitPrintAndSetValue( float waitTime, Action<int> setTheNewValue )
{
    yield return new WaitForSeconds( waitTime );
    print( "WaitAndPrint " + Time.time );
    int newValueToSet = 42;
    setTheNewValue( newValueToSet );
}

If after your delay you need to both read and update a value, you could e.g. pass Func<int> readTheOldValue, Action<int> setTheNewValue and invoke with the following lambdas () => example.Variable, theNewValue => example.Variable = theNewValue

Here's more generic example:

void Delay( float waitTime, Action act )
{
    StartCoroutine( DelayImpl( waitTime, act ) );
}

IEnumerator DelayImpl( float waitTime, Action act )
{
    yield return new WaitForSeconds( waitTime );
    act();
}

void Example()
{
    Delay( 2, () => {
        print( "After the 2 seconds delay" );
        // Update or get anything here, however you want.
    } );
}
Soonts
  • 20,079
  • 9
  • 57
  • 130
  • If by "FW2" you mean "Mono 2.6 inside Unity3D" the answer is they are compatible. I don't know where you can check but you can try it yourself: I was using `Func<>`, `Action<>` and lambdas in Unity3D in ~2011, it was already there and worked great. – Soonts Mar 11 '14 at 15:18
  • Yes, sorry, I didn't check it... :P Action delegate: http://msdn.microsoft.com/en-us/library/018hxwa8(v=vs.110).aspx – z3nth10n Mar 11 '14 at 15:22
  • BTW, the exact .NET framework in Unity3D is not 2.0. The functionality is somewhere between 2.0 and 3.5, IMO closer to the 3.5 (you already have generics, lambdas and even some LINQ in Unity3D). – Soonts Mar 11 '14 at 15:36
  • Well, I have a little problem, I want to set a color to a GUIStyle, the problem is that If I put Action all the properties/attributes will not be accepted by the compiler so how can I solve that? – z3nth10n Mar 11 '14 at 16:26
  • Use my "more generic example", in the block of code containing "Update or get anything here" comment, set any value of any objects you like. – Soonts Mar 11 '14 at 16:56
  • I have another problem and is that I want to use out, to refer my Static varaible, but I can't because I cannot use a ref or out statment in lambdas function... – z3nth10n Mar 11 '14 at 20:40
  • Yes, for a good reason: this lambda function runs 2 seconds after the Delay method has returned. Sorry the C# has no built-in time machine. – Soonts Mar 13 '14 at 10:39
0

Is this what you want?

Thread.Sleep(time)
Jonathas Costa
  • 1,006
  • 9
  • 27
0

What you're looking for here can be accomplished using Task.Delay:

void Start()
{
    print("Starting " + Time.time);
    WaitAndPrint(2.0F);
    print("Before WaitAndPrint Finishes " + Time.time);
}
Task WaitAndPrint(float waitTime)
{
    Task.Delay(TimeSpan.FromSeconds(waitTime))
        .ContinueWith(t => print("WaitAndPrint " + Time.time));
}

You can then pass around lambdas/delegates, possibly closing over variables, to move data around your program.

Servy
  • 202,030
  • 26
  • 332
  • 449
  • 1
    I don't think there's a Task.Delay in Unity3D which is based on Mono 2.6 runtime. – Soonts Mar 11 '14 at 14:54
  • Yes, well the problem is that Unity uses FW 2... And Task class is for FW4 (http://msdn.microsoft.com/es-es/library/system.threading.tasks.task(v=vs.110).aspx) So, is there another solution? :P – z3nth10n Mar 11 '14 at 15:02