EulerAngles из Vector3 приводит к странному вращению

Я пытаюсь изменить угол поворота камеры EulerAngle X, сохраняя y и z равными 0.

Однако следующий IEnumerator приводит к странным eulerAngles, например 10, -74.653, 0.

EulerAngles из Vector3 приводит к странному вращению

Я не понимаю, как значение y может измениться в следующей функции:

private IEnumerator LerpCameraNormalRot()
{
    float duration = 0.5f;

    for (float t = 0f; t < duration; t += Time.deltaTime)
    {
        float f = Mathf.Lerp(camera.transform.eulerAngles.x, 10, t / duration);
        Vector3 vNew = new Vector3(f, 0, 0);
        camera.transform.eulerAngles = vNew;
        yield return 0;
    }
}

Разве это не странно? Я никогда не меняю значения Y и Z!

Я только хочу изменить вращение X (eulerAngle.x) с текущего значения на 10.

Спасибо вам за помощь!

это вообще возможно, что-то еще меняет это? Например, если вы закомментируете camera.transform.eulerAngles = vNew;, это все еще произойдет? Это все еще происходит, если вы раскомментируете и жестко закодируете его на camera.transform.eulerAngles = new Vector3(10f,0f,0f);?

Ruzihm 12.12.2018 22:09

Другой вопрос - вращались ли какие-нибудь из предков этого GameObject? Вы устанавливаете eulerAngles, но это приведет к другому localEulerAngles, который обозначен красным квадратом на вашем изображении. Если у объекта есть повернутые предки, они, вероятно, не будут совпадать!

Ruzihm 12.12.2018 22:17

@Ruzihm Большое спасибо !!! Да, родитель повернут. Теперь, когда я заменил eulerAngles на localEulerAngles, он работает отлично. Спасибо!!!!

tmighty 12.12.2018 22:20

@Ruzihm Не могли бы вы опубликовать свое решение Quaternion.Slerp? Это позволит избежать странных поворотов при «высоких» начальных вращениях.

tmighty 12.12.2018 22:44

Первоначально я скопировал свой комментарий к ответу, но пересмотрел рекомендацию localEulerAngles. Вместо этого я рекомендую использовать Quaternion.Slerp для поворота к месту назначения. Это обрабатывает поворот от 359 до 0 градусов, а также в случае, если вы решите изменить поворот камеры по оси y или z в будущем (например, если вы решите добавить дрожание камеры). Сейчас это показано ниже :)

Ruzihm 12.12.2018 22:45

Да, не могли бы вы опубликовать это в качестве ответа?

tmighty 12.12.2018 22:46
это уже опубликовано. Переполнение стека сегодня может быть немного медленным, поэтому вам может потребоваться обновить страницу или что-то в этом роде.
Ruzihm 12.12.2018 22:50
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
7
695
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Unity использует два представления вращения: position, eulerAngles и т. д.

  • один находится в мировом пространстве
  • другой находится в локальном пространстве

Значения, не включающие в свое имя local, находятся в мировом пространстве. Если у вашего объекта есть какие-либо родители, которые повернуты / масштабированы / переведены, вы не увидите значения, которые вы установили в Unity, поскольку инспектор Transform отображает локальные координаты.

Если вы хотите установить координаты local на точные значения, вместо этого используйте localPosition, localRotation или localEulerAngles.

На мой взгляд, вы хотите повернуть камеру вокруг своей локальной оси x на 10 ° за 0,5 секунды.

Поэтому я думаю, вы могли бы вместо этого сделать это как

private IEnumerator LerpCameraNormalRot()
{
    float duration = 0.5f;

    float initialRotationX = camera.transform.localEulerAngles.x;
    float targetRotationX = 10;

    for (float t = 0f; t < duration; t += Time.deltaTime)
    {
        float currentX = Mathf.Lerp(initialRotationX, targetRotationX, t / duration);

        camera.transform.localEulerAngles = new Vector3(currentX , 0, 0);

        // Which would be the same as using 
        // camera.transform.localRotation = Quaternion.Euler(new Vector3(currentX, 0, 0));

        yield return null;
    }

    // to be sure you have no overshooting you could set the target rotation fix here as well
    camera.transform.localEulerAngles = new Vector3(targetRotation, 0 ,0);

    // or
    // camera.transform.localRotation = Quaternion.Euler(new Vector3(targetRotation, 0, 0));
} 

Я хочу установить поворот камеры (то, что показано в инспекторе) точно на 10, 0, 0 в течение 0,5 секунды. Камера связана с объектом, который вращается.

tmighty 12.12.2018 22:23

Хорошо, достаточно честно. Как сейчас?

derHugo 12.12.2018 22:25

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

tmighty 12.12.2018 22:26

Я думаю, что он в основном делает то же самое, поэтому вы можете фактически предпочесть localEulerAngles по причинам удобочитаемости.

derHugo 12.12.2018 22:27

@tmighty Проблема в том, что не всегда будет кратчайший путь для перехода к (10,0,0). Если камера находится под углом 364 градусов x, она будет вращаться в отрицательном направлении, а не в положительном направлении. Quaternion.Slerp всегда выбирал кратчайший путь.

Ruzihm 12.12.2018 22:32

Я ошибся: ваш код сразу устанавливает камеру в конечное положение. Мне все еще нужно отладить, что здесь происходит.

tmighty 12.12.2018 22:33

Не могли бы вы переписать свое решение так, чтобы текущее значение X поворота камеры было начальным значением?

tmighty 12.12.2018 22:36

не могли бы вы проверить еще раз? после изменения поворотной части я забыл также адаптировать расчет;)

derHugo 12.12.2018 22:39

Да, сейчас это работает, но вы должны использовать Mathf.Lerp. Кроме того, я сейчас наткнулся на проблему «364 градусов», о которой вы говорили. Возможно ли, что вы также разместите это решение Quaternion.Slerp, которое не показывает эту проблему?

tmighty 12.12.2018 22:41

@tmighty нет, это решение Рузима, так зачем мне его тиражировать? Если другой ответ соответствует вашим потребностям лучше, чем примите его;)

derHugo 12.12.2018 22:42
Ответ принят как подходящий

Вы устанавливаете eulerAngles, но это приведет к другому localEulerAngles, который обозначен красным квадратом на вашем изображении. Если у объекта есть повернутые предки, они, вероятно, не будут совпадать!

Чтобы решить вашу непосредственную проблему, вы можете использовать localEulerAngles вместо eulerAngles:

float f = Mathf.Lerp(camera.transform.localEulerAngles.x, 10, t / duration);
Vector3 vNew = new Vector3(f, 0, 0);
camera.transform.localEulerAngles= vNew;

Проблема в том, что он не учитывает возможность перехода с 359 градусов на 0 градусов. Еще лучше было бы использовать Quaternion.Euler и Quaternion.Slerp для использования кватернионов, а не углов Эйлера:

private IEnumerator LerpCameraNormalRot()
{
    float duration = 0.5f;
    Quaternion startRotation = camera.transform.localRotation;
    Quaternion goalRotation = Quaternion.Euler(10f, 0f, 0f);

    for (float t = 0f; t < duration; t += Time.deltaTime)
    {   
        camera.transform.localRotation = Quaternion.Slerp(startRotation, goalRotation, t/duration);
        yield return 0;
    }

    camera.transform.localRotation = goalRotation;
}

да, я думаю, Quaternion.Slerp на самом деле более точное решение

derHugo 12.12.2018 22:45

@derHugo Вы действительно хорошо подумали об использовании Quaternions вместо прямого изменения углов Эйлера в более ранней версии вашего ответа! Только когда ты упомянул об этом, я понял, что одинокий лерп не справится с этой работой.

Ruzihm 12.12.2018 22:49

@Ruzihm Спасибо !! Да, Stackoverflow был медленным, я сначала не увидел вашего решения.

tmighty 12.12.2018 22:56

Другие вопросы по теме