我在动画作品中使用协程。而且我必须确保时机完美。例如,我需要增加超时值,设置时间和stepCount来执行此操作。我的代码如下:
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);
}
因此,当我设置time = 1f和stepCount = 1时,开始打印和结束打印之间的实时时间为1秒。 但是,当我将stepCount增加到100或更多时,保持时间= 1时,实时时间将超过1秒。 关于〜1.67f
所以我有一个问题:如何使用带有特定stepCount的协程并拥有完美的计时?我使用stepCount在blenshape,着色器变量(如不透明度)上实现更平滑的过渡。并且必须使用stepCount> = 100。
答案 0 :(得分:0)
我使用stepCount在blenshape,着色器变量(如不透明度)上实现更平滑的过渡。并且必须使用stepCount> = 100。
这些步骤都将在1
秒内完成... 但是:
您的代码以特定的{strong>帧速率最佳方式运行,60 f/s
(在PC上,在编辑器中通常更高),这导致Time.deltaTime
的“标准” {两帧之间的{1}}!
0.017 seconds
或通常使用yield return new WaitForSeconds(XY);
的任何内容等待至少一帧!
因此,当然,yield
变小时,您的功能就会中断,然后实际可能的帧速率和两帧之间的实时时间就会中断。尤其是例如当您说要每秒deltaTime
次执行此操作时。
比帧速率更频繁地更新值也是没有意义的,因为用户不会比实际渲染帧更快地注意到任何变化。
另外>=100
可能是一个性能密集的调用(不说实话),因此也可能减慢执行速度,从而导致额外的延迟。
如何使用带有特定stepCount的协程并具有完美的计时
超出一定限制,您将无法做到。
但是,为什么您需要/想要对SetBlendShapeWeight
全部使用固定的步骤?
由于value
是value
,而您实际上想要的是一个相当平滑的过渡,您只需要做
float
我仍然想以另一种方式伪造它,并以固定的步长更新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);
}
<帧速率,您可以简单地将平滑过渡的值四舍五入为该值,例如
stepCount
应该向上或向下舍入到value = Mathf.Round(value / deltaValue)) * deltaValue;
的下一个完整步骤。
还要注意,在newer Unity版本中,deltaValue
不再像在previous versions中那样自动限制在SetBlendShapeWeight
范围内。< / p>
尽管如此,大多数3D建模程序在Unity中导出的范围为[0; 100]
的模型
BlendShape权重范围包括模型中定义的最小和最大权重之间的值。