Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/335.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 统一协同程序中的错误时间_C#_Unity3d_Coroutine - Fatal编程技术网

C# 统一协同程序中的错误时间

C# 统一协同程序中的错误时间,c#,unity3d,coroutine,C#,Unity3d,Coroutine,我在动画工作中使用协同程序。我必须确保时间安排是完美的。例如,我需要增加超时值。我设置了时间和步数来执行此操作。我的代码如下所示: IEnumerator ScaleDown(float time) { print(Time.time); float value = 0f; float deltaValue = 1 / (stepCount*time); float deltaTime = 1/stepCount; while (value < 1f

我在动画工作中使用协同程序。我必须确保时间安排是完美的。例如,我需要增加超时值。我设置了时间和步数来执行此操作。我的代码如下所示:

IEnumerator ScaleDown(float time)
{
    print(Time.time);
    float value = 0f;
    float deltaValue = 1 / (stepCount*time);
    float deltaTime = 1/stepCount;
    while (value < 1f)
    {
        value += deltaValue;
        meshRenderer.SetBlendShapeWeight(1, value * 100f);
        yield return new WaitForSeconds(deltaTime);
    }
    print(Time.time);
}
IEnumerator ScaleDown(浮动时间)
{
打印(时间,时间);
浮动值=0f;
浮点增量值=1/(步数*时间);
浮动增量时间=1/步计数;
而(值<1f)
{
值+=增量值;
meshRenderer.SetBlendShapeView(1,值*100f);
收益返回新的WaitForSeconds(deltaTime);
}
打印(时间,时间);
}
所以当我设置时间=1f,步数=1时,开始和结束打印之间的实时时间是1秒。 但当我将stepCount增加到100或更多时,保持时间=1,则实时时间超过1秒。 大约1.67华氏度

所以我有一个问题:我如何使用具有特定步数的协同程序,并拥有完美的时间安排?我使用stepCount在形状、着色器变量(如不透明度)上实现更平滑的过渡。并且必须使用步长计数>=100

我使用stepCount在形状、着色器变量(如不透明度)上实现更平滑的过渡。并且必须使用步长计数>=100

这些步骤都应在
1
秒内完成但是

您的代码以特定的帧速率运行,大约
60 f/s
(在PC上和编辑器中,帧速率通常更高),这会导致两帧之间的“标准”时间
。deltaTime
约为
0.017秒

yield return new WaitForSeconds(XY);
或者通常使用
yield
的任何东西都至少等待一帧

因此,当
deltaTime
小于实际可能的帧速率和两帧之间的实时性时,您的功能就会中断。尤其是当您说希望每秒执行100次时

更新值的频率高于帧速率也是没有意义的,因为用户在实际渲染帧时不会更快地注意到任何更改

此外,
setblendshapewight
可能是一个性能要求很高的调用(老实说不知道),因此它也可能会减慢执行速度,从而导致额外的延迟


我如何使用具有特定步数的协同程序并具有完美的时间安排

超过一定限度,你就是不能

但是为什么您需要/想要对
值使用固定的步骤呢

因为
是一个
浮动
,而您实际上想要的是一个相当平稳的过渡,您可以简单地执行

IEnumerator ScaleDown(float duration)
{
    print(Time.time);
    timePassed = 0f;
    do
    {
        // a linear interpolated value between 0 and 1
        var value = timePassed / duration;
        // optionaly you could even add some ease-in and ease-out
        //value = SmoothStep(0, 1, value);

        meshRenderer.SetBlendShapeWeight(1, value * 100f);

        // increase by the time passed since last frame
        // to avoid overshooting use Mathf.Min with the remaining difference
        // between duration and passedTime
        timePassed += Mathf.Min(duration - timePassed, Time.deltaTime);
        yield return null;
    } while (timePassed < duration);
    print(Time.time);
}
它应该向上或向下取整到
deltaValue
的下一个完整步骤


还请注意,在版本中,
setBlendShapeView
不再自动限制在
[0;100]
范围内

尽管如此,大多数3D建模程序导出的模型范围为Unity中的
[0;100]

混合形状权重范围包括模型中定义的最小权重和最大权重之间的值


您可以尝试改用
waitforsecondrealtime
。然而,请注意,若在该帧中由于繁重的计算而出现延迟,那个么当然更新该帧可能需要更长的时间。。这可能是原因吗?请注意,对于小于实际帧速率的值,设置
yield return WaitForSeconds
是没有意义的
WaitForSeconds
将始终至少等待下一帧,即使
t
为0。这适用于所有
yield
语句。@Draco18s是的,谢谢您提供的信息。。实际上是有意义的,因为无论如何,
yield
至少被调用过一次。谢谢)非常有用,我知道了一些新的东西)@kerkаааAliceаu和аAlex很乐意帮助!如果此答案解决了您的问题,请随时接受

value = Mathf.Round(value / deltaValue)) * deltaValue;