Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/unity3d/4.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# 统一2D。如何在协同程序中平滑地旋转对象?_C#_Unity3d - Fatal编程技术网

C# 统一2D。如何在协同程序中平滑地旋转对象?

C# 统一2D。如何在协同程序中平滑地旋转对象?,c#,unity3d,C#,Unity3d,我是这里的新手,但我会尽可能清晰地描述。(这并不重要,只是为了澄清)所以我想在1秒内旋转一个对象405度,在按下空格键时只旋转一次。我认为应该使用协同程序来完成,所以我写了如下内容: private void Update() { if (Input.GetKeyDown(KeyCode.Space)) { StopAllCoroutines(); //to prevent overlapping Start

我是这里的新手,但我会尽可能清晰地描述。(这并不重要,只是为了澄清)所以我想在1秒内旋转一个对象405度,在按下空格键时只旋转一次。我认为应该使用协同程序来完成,所以我写了如下内容:

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的书,并考虑实施它,但我并不真正理解它是如何工作的,有些东西对我不起作用,所以我走了一条更容易理解的道路。链接看起来很有趣,我会检查的,谢谢