Quaternion.Slerp по оси X и Z без оси Y - PullRequest
6 голосов
/ 04 июля 2019

Quaternion Rotation Я пытаюсь повернуть проигрыватель вокруг осей X, Y и Z.Ось Y не должна двигаться от последнего угла.Например, если я поверну на 45 градусов влево, игрок не должен поворачиваться обратно до 0. Игроковые оси X и Z поворачивают максимум на 30 градусов, затем, когда вход больше не используется, установите значение 0.

Путем проб и ошибок я наконец-то получил свой угол Y, чтобы не допустить Slerp обратно к 0. Однако X и Z по-прежнему считают Y равным 0 градусов.Плеер вращается (предположим, что на 45 градусов влево), но движение вдоль X и Z такое, как если бы Y равнялся 0 градусам.

Я читал статьи и темы и смотрел видео в нескольких доменах, включаяно не ограничиваясь, StackOverflow, форумы Unity, Unity API и видео YouTube.

Видео текущей игры - обратите внимание на выхлоп двигателя - X и Z никогда не меняются на новые нормальные значения вида камеры./ Направление игрока Y.

        void Update()
    {
        if(!controller.isGrounded)
        {

            //Three degree's
            moveDirection = new Vector3(Input.GetAxis("Horizontal"), Input.GetAxis("Thrust"), Input.GetAxis("Vertical"));
            moveDirection *= speed;

            //rotate around Y-Axis
            transform.Rotate(0, Input.GetAxis("Yaw") * rotationSpeed, 0);
            float currentY = transform.eulerAngles.y; //save Y for later

            //rotation around X and Z
            float tiltAroundX = Input.GetAxis("Vertical") * tiltAngle;
            float tiltAroundZ = -1 * (Input.GetAxis("Horizontal") * tiltAngle);

            Quaternion targetRotation = Quaternion.Euler(tiltAroundX, currentY, tiltAroundZ);

            Vector3 finalRotation = Quaternion.Slerp(transform.rotation, targetRotation, smooth).eulerAngles;
            finalRotation.y = currentY; //reintroduce Y
            transform.rotation = Quaternion.Euler(finalRotation);

        controller.Move(moveDirection * Time.deltaTime);
    }

Ответы [ 2 ]

3 голосов
/ 05 июля 2019

После дальнейших исследований, которые ведут меня по разным направлениям, я обнаружил, что есть две проблемы.Обе проблемы вращались вокруг факта, что ось Z никогда не нормализовалась до новой степени оси Y после вращения.@Ruzihm, решил проблему с вращением.Я решил тогда видимую проблему движения.Который стал легко видимым, когда вращение работало должным образом.

По сути, ось Z (transform.forward) должна быть пересчитана после любого изменения вращения по оси Y (Vector3.up).Как только вы получите новый нормальный (transform.forward), вектор движения должен быть сглажен в плоскость, чтобы игрок не мог погрузиться в поверхность мира.Спасибо @Ruzihm за вашу помощь.

Вот новый код:

//Three degree's
moveDirection = new Vector3(Input.GetAxis("Horizontal"),
                            Input.GetAxis("Thrust"),
                            Input.GetAxis("Vertical"));

//Normalize the movement direction and flatten the Plane
moveDirection = transform.TransformDirection(moveDirection);
moveDirection = Vector3.ProjectOnPlane(moveDirection, Vector3.up);

moveDirection *= speed;

// collect inputs
float yaw = Input.GetAxis("Yaw") * rotationSpeed;
float pitch = Input.GetAxis("Vertical") * tiltAngle;
float roll = -1 * (Input.GetAxis("Horizontal") * tiltAngle);

// Get current forward direction projected to plane normal to up (horizontal plane)
Vector3 forwardCurrent = transform.forward
                        - Vector3.Dot(transform.forward, Vector3.up) * Vector3.up;
// Debug to view forwardCurrent
Debug.DrawRay(transform.position, forwardCurrent * 2, Color.white);

// create rotation based on forward
Quaternion targetRotation = Quaternion.LookRotation(forwardCurrent);

// rotate based on yaw, then pitch, then roll. 
// This order prevents changes to the projected forward direction

targetRotation = targetRotation * Quaternion.AngleAxis(yaw, Vector3.up);


// Debug to see forward after applying yaw
Debug.DrawRay(transform.position, targetRotation * Vector3.forward, Color.red);

targetRotation = targetRotation * Quaternion.AngleAxis(pitch, Vector3.right);
targetRotation = targetRotation * Quaternion.AngleAxis(roll, Vector3.forward);

transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, smooth);


controller.Move(moveDirection * Time.deltaTime);
2 голосов
/ 04 июля 2019

Кажется, что есть некоторые неверные предположения о порядке поворотов, которые применяются при работе с углами Эйлера.Ролл применяется, затем шаг, затем, наконец, рысканиеЭто означает, что поддержание того же рыскания, а затем установка крена и тангажа на ноль (или даже просто смена крена) могут полностью изменить сглаженное направление, с которым вы сталкиваетесь.

Это может помочь вращению на повороте, сгладить впереднаправление (то есть проекция на полностью горизонтальную плоскость). Затем создайте вращение, основанное на том (используя Quaternion.LookRotation), которое вы затем сможете поворачивать по каждой оси вручную.

if(!controller.isGrounded)
{

    //Three degree's
    moveDirection = new Vector3(Input.GetAxis("Horizontal"), 
                                Input.GetAxis("Thrust"), 
                                Input.GetAxis("Vertical"));
    moveDirection *= speed;

    // collect inputs
    float yaw = Input.GetAxis("Yaw") * rotationSpeed;
    float pitch = Input.GetAxis("Vertical") * tiltAngle;
    float roll = -1 * (Input.GetAxis("Horizontal") * tiltAngle);

    // Get current forward direction projected to plane normal to up (horizontal plane)
    Vector3 forwardCurrent = transform.forward 
                            - Vector3.Dot(transform.forward,Vector3.up) * Vector3.up;

    // Debug to view forwardCurrent
    Debug.DrawRay(transform.location, forwardCurrent, Color.white, 0f, false);

    // create rotation based on forward
    Quaternion targetRotation = Quaternion.LookRotation(forwardCurrent);

    // rotate based on yaw, then pitch, then roll. 
    // This order prevents changes to the projected forward direction

    targetRotation = targetRotation * Quaternion.AngleAxis(yaw, Vector3.up);


    // Debug to see forward after applying yaw
    Debug.DrawRay(transform.location, targetRotation * Vector3.forward, Color.red, 0f, false);

    targetRotation = targetRotation * Quaternion.AngleAxis(pitch, Vector3.right);
    targetRotation = targetRotation  * Quaternion.AngleAxis(roll, Vector3.forward);

    transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, smooth);

    //debug new forward/up
    Debug.DrawRay(transform.location, Transform.forward, Color.blue, 0f, false);
    Debug.DrawRay(transform.location, Transform.up, Color.green, 0f, false);

    controller.Move(moveDirection * Time.deltaTime);
}

Этоможет считаться частичным ответом, потому что возможность определить «сплющенное вперед» направление и изменить порядок применения ротации компонентов полезна для ответа на ваш вопрос, но может оказаться недостаточной для получения полного эффекта, который вы хотите, в зависимости от деталей.

В качестве идентификатора вы можете рассмотреть возможность использования Quaternion.RotateTowards вместо Quaternion.Slerp, если хотите убедиться, что оно действительно достигнет целевого вращения, а не бесконечно приближается к нему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...