Проблема единства с Cinemachine при повороте символа

#c# #unity3d #game-engine #cinemachine

#c# #unity3d #игровой движок #cinemachine

Вопрос:

Я пытаюсь реализовать 3D-движение персонажа от третьего лица, используя жесткое тело и Cinemachine. Персонаж должен иметь возможность ходить по земле и потолку, а также по стенам (только по левой и правой стенам, если смотреть на положительную ось X).

Я добился этого, добавив / изменив постоянную силу к жесткому телу, чтобы изменить направление силы тяжести и повернуть персонажа на x для вверх и вниз и z для вправо и влево.

В CinemachineBrain для преобразования символов установлено переопределение «Вверх по миру», а режим привязки CinemchineFreeLook установлен на «Простое следование с помощью «Вверх по миру»». Это позволяет вращать орбиты камеры / cinemachine относительно вращения символов.

На данный момент я реализовал 4 метода в моем сценарии PlayerMovement, по одному для каждого направления гравитации (вверх, вниз, влево, вправо), каждый из которых выполняет в основном то же самое, только с измененным вращением и гравитацией.

Методы MoveUp() и moveDown() работают так, как ожидалось.

Но я не могу заставить работать методы moveLeft() и moveRight().

Проблема в том, что Персонаж не может выполнить поворот на 360 градусов (здесь по оси x) при добавлении угла камеры, а просто поворот на 180 градусов при обращении к положительному или отрицательному x (такое ощущение, что на оси y есть невидимая стена.

Я почему-то ожидаю, что проблема здесь в Cinemachine / Camera.main.transform.eulerAngles.x; , но я не могу понять, в чем именно она заключается.

Это мой первый проект в Unity / разработке игр в целом — поэтому я надеюсь, что я предоставил всю необходимую информацию.

Спасибо за ответы.

И вот мой сценарий:

(Я следовал этому руководству, чтобы реализовать базовое движение и изменил его для работы с жестким телом:https://youtu.be/4HpC—2iowE)

 public class PlayerMovement : MonoBehaviour
{

    public float walkSpeed = 5f;
    public float runSpeed = 15f;
    public float idleSpeed = 0f;

    public string gravityDiretion = "down";
    public ConstantForce gravity = new ConstantForce();
    private float actualSpeed;

    public float turnSmoothing = 0.1f;
    float turnSmoothVelocity;
    private Rigidbody character;


    private void Start()
    {
       character = GetComponent<Rigidbody>();
       gravity = gameObject.AddComponent<ConstantForce>();
    }
    private void FixedUpdate()
    {
        Move();
    }


    private void Move() 
    {
        if (gravityDiretion.Equals("up"))
        {
            MoveUp();
        }
        else if (gravityDiretion.Equals("down"))
        {
            MoveDown();
        }
        else if (gravityDiretion.Equals("right"))
        {
            MoveRight();
        }
        else if (gravityDiretion.Equals("left"))
        {
            MoveLeft();
        }
    }

    private void MoveUp()
    {
        gravity.force = new Vector3(0.0f, 9.81f, 0.0f);

        if (Input.GetKey(KeyCode.LeftShift))
        {
            actualSpeed = runSpeed;
        }
        else
        {
            actualSpeed = walkSpeed;
        }

        float horizonal = Input.GetAxisRaw("Horizontal"); // 1 = left -1 righ
        float vertical = Input.GetAxisRaw("Vertical"); // 1 = forward -1 bakwadrd
        Debug.Log("Axis Vertical = "   vertical);
        Debug.Log("Axis Horizontal = "   horizonal);

        Vector3 direction = new Vector3(horizonal, 0f, -vertical).normalized; //normalize to not moving faster when pressing two keys to walk diagonal


        if (direction.magnitude >= 0.1f) // If lenght of the vecctor is > 0
        {
            //Character Rotation
            float targetAngle = Mathf.Atan2(direction.x, direction.z) * Mathf.Rad2Deg   Camera.main.transform.eulerAngles.y; // The angle the character should turn to face forward
            Debug.Log("targetAngle = "   targetAngle);
            float smoothedAngle = Mathf.SmoothDampAngle(transform.eulerAngles.y, targetAngle, ref turnSmoothVelocity, - turnSmoothing);
            Debug.Log("smoothedAngle = "   smoothedAngle);
            character.MoveRotation(Quaternion.Euler(180f, smoothedAngle, 0f));

            //Character Movement
            Vector3 moveDir = Quaternion.Euler(180f, targetAngle, 0f) * Vector3.forward;
            Debug.Log("Movedir = "   moveDir.ToString());
            character.MovePosition(transform.position   moveDir.normalized * actualSpeed * Time.fixedDeltaTime);
        }
        else
        {
            actualSpeed = 0f;
        }
    }

    private void MoveDown()
    {
        //Gravity
        gravity.force = new Vector3(0.0f, -9.81f, 0.0f);

        if (Input.GetKey(KeyCode.LeftShift))
        {
            actualSpeed = runSpeed;
        }
        else
        {
            actualSpeed = walkSpeed;
        }

        float horizonal = Input.GetAxisRaw("Horizontal"); // 1 = left -1 righ
        float vertical = Input.GetAxisRaw("Vertical"); // 1 = forward -1 bakward
        Debug.Log("Axis Vertical = "   vertical);
        Debug.Log("Axis Horizontal = "   horizonal);

        Vector3 direction = new Vector3(horizonal, 0f, vertical).normalized; 

        if (direction.magnitude >= 0.1f) 
        {
            //Character Rotation
            float targetAngle = Mathf.Atan2(direction.x, direction.z) * Mathf.Rad2Deg   Camera.main.transform.eulerAngles.y;
            float smoothedAngle = Mathf.SmoothDampAngle(transform.eulerAngles.y, targetAngle, ref turnSmoothVelocity, turnSmoothing);
            character.MoveRotation(Quaternion.Euler(0f, smoothedAngle, 0f));

            //Character Movement
            Vector3 moveDir = Quaternion.Euler(0f, targetAngle, 0f) * Vector3.forward;
            Debug.Log("Movedir = "   moveDir.ToString());
            character.MovePosition(transform.position   moveDir.normalized * actualSpeed * Time.fixedDeltaTime);
        }
        else
        {
            actualSpeed = 0f;
        }
    }

    private void MoveRight()
    {
        //Gravity
        gravity.force = new Vector3(9.81f, 0.0f, 0.0f);

        if (Input.GetKey(KeyCode.LeftShift))
        {
            actualSpeed = runSpeed;
        }
        else
        {
            actualSpeed = walkSpeed;
        }

        float horizonal = Input.GetAxisRaw("Horizontal");
        float vertical = Input.GetAxisRaw("Vertical");
        Debug.Log("Axis Vertical = "   vertical);
        Debug.Log("Axis Horizontal = "   horizonal);

        Vector3 direction = new Vector3( 0f, horizonal, vertical).normalized; 


        if (direction.magnitude >= 0.1f) 
        {

            float targetAngle = Mathf.Atan2(direction.y, direction.z) * Mathf.Rad2Deg   Camera.main.transform.eulerAngles.x;
            Debug.Log("targetAngle = "   targetAngle);
            float smoothedAngle = Mathf.SmoothDampAngle(transform.eulerAngles.x, targetAngle, ref turnSmoothVelocity, turnSmoothing);
            Debug.Log("smoothedAngle = "   smoothedAngle);
            character.MoveRotation( Quaternion.Euler(targetAngle, 0f , 90f));

            //Character Movement
            Vector3 moveDir = Quaternion.Euler(targetAngle, 0.0f, 90f) * Vector3.forward;
            Debug.Log("Movedir = "   moveDir.ToString());
            character.MovePosition(transform.position   moveDir.normalized * actualSpeed * Time.fixedDeltaTime);
        }
        else
        {
            actualSpeed = 0f;
        }
    }


    private void MoveLeft()
    {
        //Gravity
        gravity.force = new Vector3(-9.81f, 0.0f, 0.0f);

        if (Input.GetKey(KeyCode.LeftShift))
        {
            actualSpeed = runSpeed;
        }
        else
        {
            actualSpeed = walkSpeed;
        }

        float horizonal = Input.GetAxisRaw("Horizontal"); 
        float vertical = Input.GetAxisRaw("Vertical"); 
        Debug.Log("Axis Vertical = "   vertical);
        Debug.Log("Axis Horizontal = "   horizonal);

        Vector3 direction = new Vector3(0f, horizonal, vertical).normalized; 


        if (direction.magnitude >= 0.1f)
        {
            //Character Rotation
            float targetAngle = Mathf.Atan2(direction.z, direction.y) * Mathf.Rad2Deg   Camera.main.transform.eulerAngles.x; 
            float smoothedAngle = Mathf.SmoothDampAngle(transform.eulerAngles.x, targetAngle, ref turnSmoothVelocity, turnSmoothing);
            character.MoveRotation(Quaternion.Euler(smoothedAngle, 0f, -90f));

            //Character Movement
            Vector3 moveDir = Quaternion.Euler(targetAngle, 0.0f, -90f) * Vector3.right;
            Debug.Log("Movedir = "   moveDir.ToString());
            character.MovePosition(transform.position   moveDir.normalized * actualSpeed * Time.fixedDeltaTime);
        }
        else
        {
            actualSpeed = 0f;
        }
    }



    public void ChangeDravityDirection(string newGravityDirection)
    {
        gravityDiretion = newGravityDirection;  
    }