Страница 1 из 1

Вращение камеры

СообщениеДобавлено: 14 апр 2021, 16:36
xrou
Всем привет! Пишу управление камерой, но тормоза происходят на самых элементарных вещах. Нужен поворот вокруг своей оси на 360 градусов по осям XY (Ну обычное FPS управление), но на кнопках(В теории это типо летает космический корабль). Сделал. Камера вертится. Но когда камера принимает положение "вверх ногами" управление влево вправо инвертируется. Или же просто описывает восьмерку.
Вообще не понимаю как убрать это. Подскажите как это исправить
Синтаксис:
Используется csharp
public class Player : MonoBehaviour
{
    public float RotationSpeed = 120;

    private float CurrentRotationSpeedX = 0;
    private float CurrentRotationSpeedY = 0;

    private Rigidbody m_rigidbody;


    void Start()
    {
        m_rigidbody = GetComponent<Rigidbody>();
    }

    void Update()
    {

        if (Input.GetKey(KeyCode.W) && !Input.GetKey(KeyCode.S))
        {
            CurrentRotationSpeedX = Mathf.Lerp(CurrentRotationSpeedX, -RotationSpeed, Time.deltaTime * 3);
        }
        else if (Input.GetKey(KeyCode.S))
        {
            CurrentRotationSpeedX = Mathf.Lerp(CurrentRotationSpeedX, RotationSpeed, Time.deltaTime * 3);
        }
        else
        {
            CurrentRotationSpeedX = Mathf.Lerp(CurrentRotationSpeedX, 0, Time.deltaTime * 4);
        }

        if (Input.GetKey(KeyCode.A) && !Input.GetKey(KeyCode.D))
        {
            CurrentRotationSpeedY = Mathf.Lerp(CurrentRotationSpeedY, -RotationSpeed * sign, Time.deltaTime * 3);
        }
        else if (Input.GetKey(KeyCode.D))
        {
            CurrentRotationSpeedY = Mathf.Lerp(CurrentRotationSpeedY, RotationSpeed * sign, Time.deltaTime * 3);
        }
        else
        {
            CurrentRotationSpeedY = Mathf.Lerp(CurrentRotationSpeedY, 0, Time.deltaTime * 4);
        }

        transform.RotateAround(transform.position, transform.right, CurrentRotationSpeedX * Time.deltaTime);
        transform.RotateAround(transform.position, Vector3.up, CurrentRotationSpeedY * Time.deltaTime);
    }
}

Re: Вращение камеры

СообщениеДобавлено: 14 апр 2021, 16:54
1max1
Инвертируется только AD, как я понял? Может вместо Vector3.up использовать transfrom.up? Но тогда будет еще и roll вращение мне кажется.

Re: Вращение камеры

СообщениеДобавлено: 15 апр 2021, 15:23
xrou
1max1 писал(а):Инвертируется только AD, как я понял? Может вместо Vector3.up использовать transfrom.up? Но тогда будет еще и roll вращение мне кажется.

Если использовать transform.up то происходит вращение по Z(roll). А что за "AD"?

Re: Вращение камеры

СообщениеДобавлено: 15 апр 2021, 15:44
1max1
А что за "AD"?

AD это кнопки A и D.
Если использовать transform.up то происходит вращение по Z(roll).

Тогда проверяй значение transform.up.y, в зависимости от знака меняй вектор либо Vector3.up либо Vector3.down.

Re: Вращение камеры

СообщениеДобавлено: 15 апр 2021, 16:48
xrou
1max1 писал(а):
А что за "AD"?

AD это кнопки A и D.
Если использовать transform.up то происходит вращение по Z(roll).

Тогда проверяй значение transform.up.y, в зависимости от знака меняй вектор либо Vector3.up либо Vector3.down.

Уже попровбовал, но не могу получить угол поворота камеры в "нормальных" углах 360*. И еще вопрос. Использую акселерометр и у него нулевое положение по оси x - это лежа. Как сместить эту ориентацию, что бы телефон стоящий на ребре, считался как в положении лежа? https://prnt.sc/11g69ai

Re: Вращение камеры

СообщениеДобавлено: 30 апр 2021, 14:07
Oducceu
1. При использовании вращения посредством _Transform ты получаешь определенные артефакты в виде проверки и отсечки углов на предмет -360.0 ... +360.0 градусов (аналог LerpAngle) инкрементация или декрементация которых даст скачки в противоположных направлениях, кроме того существует «Гимбальный замок» / «Gimbal Lock» (набор углов при котором дальнейшее их поведение уже не является объективным и понимаемым без математических алгоритмов, такое происходит при совпадении нескольких осей вращения: посмотреть вверх на 90 градусов и повращаться влево-вправо, в результате получим вращение по оси Y из которой больше не выйдем, в авиации это называется "Штопор").

Выход:
Все вращения считай в отдельной переменной без участия в ней чтения из Transform.rotation и подобных вещей, минуя вышеуказанные отсечки.
Лишь после проведения вычислений указывай явно ротацию объекта

private void Update ()
{
...
_Transform.eulerAngles = _EulerAngles;
// _Transform.rotation = Quaternion.Euler (_EulerAngles);
}

Компонент <Transform> самостоятельно сделает все нужные отсекания.


2. Задать начальное не нулевое отклонение (гистерезис) акселерометру, можно считав показания из него в момент инициализации в отдельную переменную, например так:

private Vector3 _Offset = new Vector3 (0.0f, 0.0f, 0.0f);

private void Start ()
{
_Offset = new Vector3 (AccelerometerEulerAngles);
}

и, в последствии, учесть это отклонение в конечных углах:

private void Update ()
{
....
Transform.eulerAngles = _EulerAngles - _Offset;
}