【问题标题】:Unity3D: Trying to make a custom Sleep/Wait function in C#Unity3D:尝试在 C# 中创建自定义睡眠/等待功能
【发布时间】:2014-04-15 05:16:58
【问题描述】:

这一切都始于昨天我使用该代码制作 sn-p 时:

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);
}

发件人:http://docs.unity3d.com/Documentation/ScriptReference/MonoBehaviour.StartCoroutine.html

问题是我想从该类型的类中设置一个静态变量:

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

}

问题出在哪里?问题是,如果将该变量放在函数的参数中,则此“时间参数”将在函数结束时被销毁......所以,我搜索了一下,我记得:

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

发件人:http://msdn.microsoft.com/es-es/library/ms228503.aspx

但是,(总是有一个“但是”)Iterators cannot have ref or out...所以我决定创建自己的等待函数,因为 Unity 没有睡眠功能...

这是我的代码:

    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.");

该代码有什么问题?问题是它是非常粗暴的代码,因为它会产生内存泄漏、错误,当然还有应用程序的播放...

那么,你建议我做什么?

【问题讨论】:

  • 你很可能不想睡觉。这很少是解决方案。你想要什么很难说。至少,我无法理解这个问题。
  • 问题是我想知道是否有替代方案,Thread.Sleep(游戏冻结)、Tasks(FW4)或 Yield 返回新的 WaitForSeconds(out 和 ref 与迭代器不兼容在这种类型的退货中使用)

标签: c# unity3d delay


【解决方案1】:

你可以这样做:

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 );
}

如果在延迟之后您需要读取和更新一个值,例如,您可以通过 Func&lt;int&gt; readTheOldValue, Action&lt;int&gt; setTheNewValue 并使用以下 lambdas () =&gt; example.Variable, theNewValue =&gt; example.Variable = theNewValue 调用

这里是更通用的例子:

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.
    } );
}

【讨论】:

  • 如果“FW2”是指“Unity3D 中的 Mono 2.6”,答案是它们是兼容的。我不知道您可以在哪里查看,但您可以自己尝试一下:我在 2011 年左右在 Unity3D 中使用了 Func&lt;&gt;Action&lt;&gt; 和 lambda,它已经在那里并且运行良好。
  • 是的,抱歉,我没有检查... :P 行动代表:msdn.microsoft.com/en-us/library/018hxwa8(v=vs.110).aspx
  • 顺便说一句,Unity3D 中的确切 .NET 框架不是 2.0。功能介于 2.0 和 3.5 之间,IMO 更接近 3.5(Unity3D 中已经有泛型、lambda 甚至一些 LINQ)。
  • 好吧,我有一个小问题,我想给一个 GUIStyle 设置颜色,问题是如果我把 Action 所有的属性/属性都不会被编译器接受所以我该如何解决?
  • 使用我的“更通用的示例”,在包含“在此处更新或获取任何内容”注释的代码块中,设置您喜欢的任何对象的任何值。
【解决方案2】:

这是你想要的吗?

Thread.Sleep(time)

【讨论】:

  • 不,实际上不是。阅读打印信息的文本。这不会产生所需的输出。
  • 你不应该阻塞 Unity3D 中的 GUI 线程。您的游戏将冻结。
【解决方案3】:

您在此处查找的内容可以使用 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));
}

然后您可以传递 lambdas/delegates,可能关闭变量,以在您的程序中移动数据。

【讨论】:

  • 我认为 Unity3D 中没有基于 Mono 2.6 运行时的 Task.Delay。
  • 是的,问题是 Unity 使用 FW 2... 而 Task 类适用于 FW4 (msdn.microsoft.com/es-es/library/…) 那么,还有其他解决方案吗? :P
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-12
  • 1970-01-01
相关资源
最近更新 更多