旋转脚本问题?

4

当用户释放鼠标按钮时,调用此脚本:

float rot_duration = 3f;
float rot_speed = 1.8f;
Quaternion final_rot;

void Start()
{
    cubeMesh = GameObject.FindWithTag("CubeMesh");

    Vector3 initial_rot = transform.rotation.eulerAngles;
    final_rot = Quaternion.Euler(new Vector3(initial_rot.x, initial_rot.y, 180));
}

public void Update()
{
    if (Input.GetMouseButtonUp(0)) 
    {
        StartCoroutine (DelayRotate (0.1F));
    }
}

IEnumerator DelayRotate(float waitTime)
{
        yield return new WaitForSeconds (waitTime);
        float rot_elapsedTime = 0.0F;
        while (rot_elapsedTime < rot_duration) {
        cubeMesh.transform.rotation = Quaternion.Slerp (transform.rotation, final_rot, rot_elapsedTime);
            rot_elapsedTime += Time.deltaTime * rot_speed;
            yield return null;
        }
}

这个脚本让一个游戏对象在鼠标松开后0.1秒开始旋转。问题是它会在快速翻转游戏对象后再开始旋转。
我认为这是由于final_rot2 = Quaternion.Euler(new Vector3(initial_rot.x, initial_rot.y, 180));中的180值导致的翻转。应该怎么做呢?

@ Prix,“while” 循环必须存在,否则它无法旋转。 - user6068287
永远不要使用四元数 - 无论什么原因 - 永远。 使用“Rotate”调用。 transform.Rotate(Time.deltaTime,0,0); 许多示例在此处http://docs.unity3d.com/ScriptReference/Transform.Rotate.html - Fattie
final_rot被初始化为什么? - Programmer
@程序员问题已编辑。 - user6068287
我在你的代码中发现了错误。看看我的答案。 - Programmer
2个回答

1
我仔细查看了代码,发现了两个错误。 1. 导致问题的唯一错误是:
cubeMesh.transform.rotation = Quaternion.Slerp (transform.rotation, final_rot, rot_elapsedTime);

上面的人说你应该用cubeMesh.transform.rotation替换transform.rotation。这很接近但是行不通。你需要做的是在while loop之外获取GameObject的当前位置并将其存储在某个地方,然后你可以在while loop内随时使用它。例如,

Quaternion currentLocation = cubeMesh.transform.rotation;
while(...){
  cubeMesh.transform.rotation = Quaternion.Slerp (currentLocation, final_rot, rot_elapsedTime);
...Other codes
}

2. 我发现的另一个错误是,看起来你正在尝试在一定时间内旋转物体,因为你有一个名为rot_duration的变量。

如果这是真的,那么当你执行Quaternion.Slerp(transform.rotation, final_rot, rot_elapsedTime);时,你失败了。

如果你想让物体在rot_duration的时间内旋转,将rot_elapsedTime更改为rot_elapsedTime / rot_duration。同时删除rot_speed,因为如果你想要在一定时间内旋转,它不会起作用。

如果这不是你想做的事情,那么我发现的第一个错误应该可以解决你的问题。

你的最终代码应该像下面这样:

float rot_duration = 10f;
float rot_speed = 3f;
Quaternion final_rot;
GameObject cubeMesh;

void Start()
{
    cubeMesh = GameObject.FindWithTag("CubeMesh");

    Vector3 initial_rot = transform.rotation.eulerAngles;
    final_rot = Quaternion.Euler(new Vector3(initial_rot.x, initial_rot.y, 180));
}

public void Update()
{
    if (Input.GetMouseButtonUp(0))
    {
        StartCoroutine(Delay(1));
    }
}

IEnumerator Delay(float waitTime)
{
    yield return new WaitForSeconds(waitTime);
    float rot_elapsedTime = 0.0F;

    //Get the current rotation 
    Quaternion currentLocation = cubeMesh.transform.rotation;

    while (rot_elapsedTime < rot_duration)
    {
        rot_elapsedTime += Time.deltaTime;
        cubeMesh.transform.rotation = Quaternion.Slerp(currentLocation, final_rot, rot_elapsedTime / rot_duration);
        yield return null;
    }
}

0
这里的问题是它不会每一帧都更新。我看到你添加了Time.deltaTime,但它并不会每一帧都更新,它只会在当前帧使用该值多次,因为你在一个update中完成了所有操作。
这段代码可能有效:
float rot_duration = 10f;
float rot_speed = 3f;
float rot_elapsedTime = 3f;
Quaternion final_rot;

public void Update()
{
    if (Input.GetMouseButtonUp(0)) 
    {
        StartCoroutine (Delay (1));
    }
    if (rot_elapsedTime < rot_duration) {
        cubeMesh.transform.rotation = Quaternion.Slerp (transform.rotation, final_rot, rot_elapsedTime);
        rot_elapsedTime += Time.deltaTime * rot_speed;
}

IEnumerator Delay(float waitTime)
{
   yield return new WaitForSeconds (waitTime);
   rot_elapsedTime = 0.0F;
}

但是就像已经说过的那样,transform.Rotate可能更好一些。

编辑:在原发布者更新了新代码并加入了1秒延迟后进行了更新。


抱歉,一开始我没有注意到1秒的延迟,但我认为你的问题在于你有一个while循环,这意味着你一次性完成了整个旋转,而没有更新帧。我已经根据你的新代码编辑了我的答案。 - Ole Fredrik Borgundvåg Berg
他的 while 循环没有问题,它返回 null,这与 WaitForEndOfFrame() 的效果相同。 - JoRouss

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接