Как повернуть объект с использованием кватернионов вокруг осей x и z, чтобы сохранить неизменной координату y?

Как можно повернуть объект только по осям x и z, сохраняя неизменной координату Y? Решение с использованием теории кватернионов представляется сложным для меня. Вот мой текущий код: 

```C#
public class PlatformRotator : MonoBehaviour
{
    [SerializeField] private float _speed;
    private Rigidbody _rigidbody;
    private SwipeReader _input;

    private void Awake()
    {
        _rigidbody = GetComponent<Rigidbody>();
        _input = GetComponent<SwipeReader>();
    }

    private void Start()
    {
        _input.OnDirectionChanged += OnSwipingHandler;
    }

    private void OnSwipingHandler(Vector2 direction)
    {
        var currentPosition = transform.localRotation;
        var direction3D = new Vector3(direction.y, 0,-direction.x);
        var rotate = UnityEngine.Quaternion.Euler(direction3D) * currentPosition;
        _rigidbody.MoveRotation(rotate);
    }

    private void OnDrawGizmos()
    {
     
    }
} 
```

Я пробовал обнулить координату Y в направлении, а также использовал флаг "freeze rotation Y" в компоненте rigidbody, но координата Y по-прежнему меняется. Пожалуйста, помогите мне разобраться с этой проблемой.
  • 2 октября 2023 г. 18:27
Ответы на вопрос 1
Для поворота объекта только по осям x и z с сохранением неизменной координаты y, вы можете использовать следующий код:

```C#
public class PlatformRotator : MonoBehaviour
{
    [SerializeField] private float _speed;
    private Rigidbody _rigidbody;
    private SwipeReader _input;

    private void Awake()
    {
        _rigidbody = GetComponent<Rigidbody>();
        _input = GetComponent<SwipeReader>();
    }

    private void Start()
    {
        _input.OnDirectionChanged += OnSwipingHandler;
    }

    private void OnSwipingHandler(Vector2 direction)
    {
        var currentRotation = transform.rotation;

        // Обнуляем компоненту Y в направлении
        direction.y = 0f;

        // Создаем новый кватернион, поворачивая его только по осям x и z
        // Используем Direction3D.normalized, чтобы сохранить единичную длину вектора
        var targetRotation = Quaternion.Euler(direction.normalized * _speed) * currentRotation;

        // Применяем новый поворот объекта, сохраняя неизменной координату Y
        _rigidbody.MoveRotation(targetRotation);
    }

    private void OnDrawGizmos()
    {
     
    }
}
```

В этом коде мы обнуляем компоненту y ​​в векторе направления, чтобы объект не вращался вокруг этой оси. Затем мы создаем новый кватернион, поворачивая его только по осям x и z, используя рассчитанный вектор направления. Наконец, мы применяем новый поворот к объекту, используя метод `MoveRotation` вместо `rotation`, чтобы сохранить стабильность физики ригидбоди.

Обратите внимание, что в этом коде нет контроля ограничения поворота. Если вы хотите добавить ограничения вращения по осям x и z, вам может потребоваться дополнительная логика.
Похожие вопросы