C# 统一2D。如何在协同程序中平滑地旋转对象?
我是这里的新手,但我会尽可能清晰地描述。(这并不重要,只是为了澄清)所以我想在1秒内旋转一个对象405度,在按下空格键时只旋转一次。我认为应该使用协同程序来完成,所以我写了如下内容:C# 统一2D。如何在协同程序中平滑地旋转对象?,c#,unity3d,C#,Unity3d,我是这里的新手,但我会尽可能清晰地描述。(这并不重要,只是为了澄清)所以我想在1秒内旋转一个对象405度,在按下空格键时只旋转一次。我认为应该使用协同程序来完成,所以我写了如下内容: private void Update() { if (Input.GetKeyDown(KeyCode.Space)) { StopAllCoroutines(); //to prevent overlapping Start
private void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
StopAllCoroutines(); //to prevent overlapping
StartCoroutine(Rotate());
}
}
IEnumerator Rotate()
{
//where final finalRotation is a rotation i want to get in a result
Quaternion finalRotation = Quaternion.Euler(0, 0, 405) * transform.rotation;
/*
using do..while to make sure that object will rotate even in case it's in same rotation as finalRotation
*/
do
{
//should smoothly rotate an object for 405deg in 1 sec but it doesnt
transform.Rotate(Vector3.forward, 405f * Time.deltaTime / 1f);
} while (transform.rotation != finalRotation);
yield return 1;
}
上面的代码工作正常,除了一个,其他一切都正常,它立即旋转对象,但不平滑。我的意思是,如果我在更新中使用这行代码,一切都会顺利进行
transform.Rotate(Vector3.forward, 405f * Time.deltaTime / 1f);
所以我的问题是:
再次感谢您,如果我在制作主题时犯了一些错误,请再次表示歉意。
yield return null
将在协同程序中等待一帧。现在您已将收益率回报率设置为1;在while循环之外,所以它不会做任何事情。在这种情况下,我将在从0->1开始的while循环中,在两个旋转之间执行lerp
或者(如果你不想做这些事情,也不想有点臃肿)使用leantween,在你旋转一次的地方,你必须等待一段时间。试一试
yield return new WaitForSeconds(0.1);
另外,当我输入这个时,另一个人回答了。它会在协同程序中立即更新,因为只有当旋转完成时,您才会让步。直到每个挂起/运行的协同程序产生或完成,帧才会被渲染,因此在这里,旋转完成,然后最终渲染帧,使其成为即时旋转 相反,您应该在循环中让步 您还应该知道
Quaternion finalRotation=Quaternion.Euler(0,0405)*transform.rotation编码>和变换.旋转(矢量3.forward,405f)根据父对象旋转,代码>可以有不同的结果,因为它们在不同的空间中旋转,第一个在全局旋转,第二个在局部旋转。这可能会导致编写的循环实际上永远不会结束
另一个问题是不能保证总和Time.deltaTime
值加起来等于1f。假设在第一帧上发生延迟,导致Time.deltaTime
非常大,2f
。你可以看到它可能永远不会结束。或者,您应该记住开始旋转,然后在每个帧上计算该帧的旋转,然后将其应用于该帧
总共:
IEnumerator Rotate()
{
Quaternion startRotation = transform.rotation;
float endZRot = 405f;
float duration = 1f;
float t = 0;
while (t < 1f)
{
time = Mathf.Min(1f, t + Time.deltaTime/duration);
Vector3 newEulerOffset = Vector3.forward * (endZRot * t);
// global z rotation
transform.rotation = Quaternion.Euler(newEulerOffset) * startRotation;
// local z rotation
// transform.rotation = startRotation * Quaternion.Euler(newEulerOffset);
yield return null;
}
}
IEnumerator Rotate()
{
四元数startRotation=transform.rotation;
浮动端Zrot=405f;
浮动持续时间=1f;
浮动t=0;
而(t<1f)
{
时间=数学分钟(1f,t+时间延迟/持续时间);
Vector3 newEulerOffset=Vector3.forward*(endZRot*t);
//全局z旋转
transform.rotation=四元数.Euler(newEulerOffset)*startRotation;
//局部z旋转
//transform.rotation=startRotation*四元数.Euler(newEulerOffset);
收益返回空;
}
}
谢谢您的详细回答。像滞后这样的事情似乎很明显,但我甚至没有把它们考虑进去。所有这些对细节的关注,非常有趣是的,愚蠢的错误。。。据我所知,有很多方法可以做到这一点。我读过关于lerp的书,并考虑实施它,但我并不真正理解它是如何工作的,有些东西对我不起作用,所以我走了一条更容易理解的道路。链接看起来很有趣,我会检查的,谢谢