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

Программирование на Юнити.

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

Сообщение xrou 14 апр 2021, 16:36

Всем привет! Пишу управление камерой, но тормоза происходят на самых элементарных вещах. Нужен поворот вокруг своей оси на 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);
    }
}
xrou
UNец
 
Сообщения: 27
Зарегистрирован: 10 сен 2018, 08:56

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

Сообщение 1max1 14 апр 2021, 16:54

Инвертируется только AD, как я понял? Может вместо Vector3.up использовать transfrom.up? Но тогда будет еще и roll вращение мне кажется.
Аватара пользователя
1max1
Адепт
 
Сообщения: 5505
Зарегистрирован: 28 июн 2017, 10:51

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

Сообщение xrou 15 апр 2021, 15:23

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

Если использовать transform.up то происходит вращение по Z(roll). А что за "AD"?
xrou
UNец
 
Сообщения: 27
Зарегистрирован: 10 сен 2018, 08:56

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

Сообщение 1max1 15 апр 2021, 15:44

А что за "AD"?

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

Тогда проверяй значение transform.up.y, в зависимости от знака меняй вектор либо Vector3.up либо Vector3.down.
Аватара пользователя
1max1
Адепт
 
Сообщения: 5505
Зарегистрирован: 28 июн 2017, 10:51

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

Сообщение xrou 15 апр 2021, 16:48

1max1 писал(а):
А что за "AD"?

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

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

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

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

Сообщение Oducceu 30 апр 2021, 14:07

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;
}
Oducceu
UNец
 
Сообщения: 5
Зарегистрирован: 15 сен 2013, 00:09


Вернуться в Скрипты

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 3