Пытаюсь сделать простую игру в Unity для GearVR. В игре у меня есть сцена, где пользователь может перемещаться по списку предметов. Элемент можно выбрать, если пользователь щелкнет, глядя на него. В части навигации пользователь должен иметь возможность использовать как движение головы, так и смахивание для поворота элементов (смещение на единицу / минус один при каждом смахивании вправо / влево).

Теперь проблема: я могу заставить всю эту работу работать с приведенным ниже кодом (установлен как компонент для родительского элемента), но вращение продолжает увеличиваться, чем больше я использую смахивания. Кажется, я не могу понять, почему ... все еще работаю над этим.
Любая помощь приветствуется 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;
    }
}

Я использую Unity 5.4.1f1 и jdk 1.8.0.

PS. Не обижайся на меня, это мой первый вопрос.
Кстати ... всем привет XD

0
arjel 25 Ноя 2016 в 19:01

2 ответа

Лучший ответ

Вы исправили большинство проблем, которые я обсуждал в разделе комментариев. Остается еще один цикл while. Прямо сейчас нет возможности выйти из этого цикла while, и это приведет к одновременному запуску нескольких экземпляров функции Rotate.

но вращение увеличивается, чем больше я использую свайпы

Решение состоит в том, чтобы сохранить ссылку на одну функцию сопрограммы, а затем остановить ее перед запуском новой.

Что-то вроде этого.

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

Вместо while (true) у вас должен быть таймер, который существует для цикла while. В это время функция Rotate работает постоянно. Вы должны остановить его после перехода от вращения к целевому вращению.

Примерно так должно работать:

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

Вот как должен выглядеть весь ваш код:

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;
    }
}

Вы можете увеличивать или уменьшать переменную duration.

1
Programmer 25 Ноя 2016 в 17:48

Попробуйте использовать Lerp из текущего вращения, а не последнего:

transform.rotation = Quaternion.Slerp(transform.rotation, to, Time.deltaTime);
1
Ludovic Feltz 25 Ноя 2016 в 16:07