简体   繁体   中英

Unity3D: no idea how to use Quaternion.Slerp(); rotation becomes faster

I'm trying to make a simple game in Unity for GearVR. In the game I have a scene where the user can navigate through a list of items. An item can be selected if the user clicks while looking at one. For the navigation part, the user should be able to use both head movement and swipe to rotate the items (shifting by one/minus one at every right/left swipe).

Now the problem: I can make all of this work with the code below (set as component to the parent of the items), but the rotation keeps increasing the more I use swipes. I can't seem to figure out why ... still working on it.
Any kind of help is appreciated XD

private void ManageSwipe(VRInput.SwipeDirection sw)
{
    from = transform.rotation;
    if (sw == VRInput.SwipeDirection.LEFT)
    {
        to = Quaternion.Euler(new Vector3(0, from.eulerAngles.y + 30, 0));           
    }
    if (sw == VRInput.SwipeDirection.RIGHT)
    {
        to = Quaternion.Euler(new Vector3(0, from.eulerAngles.y - 30, 0));
    }
    StartCoroutine(Rotate());
}

IEnumerator Rotate(bool v)
{
    while (true)
    {
        transform.rotation = Quaternion.Slerp(from, to, Time.deltaTime);           
        yield return null;
    }
}

I'm using Unity 5.4.1f1 and jdk 1.8.0.

PS. Don't be to hard on me, since this is my first question here.
By the way ... hello everyone XD

尝试从当前旋转而不是最后一个旋转使用Lerp:

transform.rotation = Quaternion.Slerp(transform.rotation, to, Time.deltaTime);

You fixed most of the problems I discussed in the comment section. One things left is still the while loop. Right now, there is no way to exit that while loop and this will result to multiple instance of the Rotate function running at the-same time.

but the rotation keeps increasing the more I use swipes

Solution is to store reference to one coroutine function then stop it before starting a new one.

Something like this.

IEnumerator lastCoroutine;
lastCoroutine = Rotate();
...
StopCoroutine(lastCoroutine);
StartCoroutine(lastCoroutine);

Instead of while (true) , you should have a timer that exists the while loop. At this time, the Rotate function is continuously running. You should make it stop after moving from the rotation to the destination rotation.

Something like this should work:

while (counter < duration)
{
    counter += Time.deltaTime;
    transform.rotation = Quaternion.Lerp(from, to, counter / duration);
    yield return null;
}

Here is what your whole code should look like:

IEnumerator lastCoroutine;

void Start()
{
    lastCoroutine = Rotate();
}

private void ManageSwipe(VRInput.SwipeDirection sw)
{

    //from = transform.rotation;
    if (sw == VRInput.SwipeDirection.LEFT)
    {
        to = Quaternion.Euler(new Vector3(0, from.eulerAngles.y + 30, 0));
    }
    if (sw == VRInput.SwipeDirection.RIGHT)
    {
        to = Quaternion.Euler(new Vector3(0, from.eulerAngles.y - 30, 0));
    }
    //Stop old coroutine
    StopCoroutine(lastCoroutine);
    //Now start new Coroutine
    StartCoroutine(lastCoroutine);
}

IEnumerator Rotate()
{
    const float duration = 2f; //Seconds it should take to finish rotating
    float counter = 0;

    while (counter < duration)
    {
        counter += Time.deltaTime;
        transform.rotation = Quaternion.Lerp(from, to, counter / duration);
        yield return null;
    }
}

You can increase or decrease the duration variable.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM