Как ограничить тангаж и крен Transform'а

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

Как ограничить тангаж и крен Transform'а

Сообщение Октав 25 авг 2023, 03:03

Как ограничить тангаж и крен Transform'а относительно горизонта(соответственно Vector.up нормаль горизонта) на заданные градусы. Что-то в духе сlamp.

Во избежание недопонимания, опишу ситуацию. Имеется трансформ. Из него нужно высчитать другой (хотя это может быть один и тот же, но не суть), "ограниченны" трансформ, в соответствии с условиями - ограничение (в градусах) тангажа и крена относительно горизонта. Т.е. нужно ограничивать углы вращения вокруг оси transform.forward(крен) на заданные углы относительно горизонта(выравнен по горизонту - угол равен нулю), и вокруг оси transform.right(тангаж) аналогично.

Сразу оговорюсь. городить матрешку из гейм обжектов мне не подходит.

Задачу можно сформулировать и по другому. Например, как ограничить отклонения "направляющей оси" трансформа(в данном случае это ось transform.up), относительно заданного произвольного направления(в данном случае это ось Vector.up). Таким образом, если поворот относительно осей transform.forward и transform.right, ограничивается на равные углы, допустимое вращения происходят в рамках некого конуса(ось конуса Vector.up в данном случае). Но мне еще и нужна возможность ограничивать углы индивидуально для вращения вокруг transform.forward и transform.right.
Изображение
Я нагородил своего гавнокода, но может есть что-то более приличное?

Синтаксис:
Используется csharp
    public float _angleForward;
    public float _angleRight;
    void Update()
    {


        reorientationMove.transform.rotation = ReorientationAngle(reorientationMove.transform, Vector3.up);

        // тут проверяю расхожение _angleForward (и _angleRight) с angleForward (и angleRight)
        _angleForward = 90f - Vector3.Angle(Vector3.up, reorientationMove.transform.forward);
        _angleRight = 90f - Vector3.Angle(Vector3.up, reorientationMove.transform.right);
    }

    public float angleForward;
    public float angleRight;
    public float angleForward01;
    public float angleRight01;

    Quaternion ReorientationAngle(Transform transf, Vector3 normal)
    {
        // замеряю углы
        angleForward = 90f - Vector3.Angle(normal, transf.forward);
        angleRight = 90f - Vector3.Angle(normal, transf.right);

        //тут типа ограничивающие условия будут, а пока просто проверяю
        /*
        float _angleForward = Mathf.Clamp(angleForward, -15f, 15f);
        float _angleRight = Mathf.Clamp(angleRight, -15f, 15f);
        */


         // это для проверки передаю, чтобы сверить корректность углов на входе и на выходе
        _angleForward = angleForward;
        _angleRight = angleRight;

        // первый вариант, работает не корректно
        angleForward01 = 1f - (_angleForward / 90f);
        angleRight01 = 1f - (_angleRight / 90f);
        Vector3 _forward = Vector3.SlerpUnclamped(normal, Vector3.Cross(transf.right, normal), angleForward01);
        Vector3 _right = Vector3.SlerpUnclamped(normal, -Vector3.Cross(transf.forward, normal), angleRight01);
        Quaternion output = Quaternion.LookRotation(_forward, Vector3.Cross(_forward, _right));

        // второй вариант, работает лучше, но все равно с погрешностью
        Quaternion output =
            Quaternion.AngleAxis(_angleRight, transf.forward) *
            Quaternion.AngleAxis(-_angleForward, transf.right) *
            Quaternion.AngleAxis(transf.eulerAngles.y, normal);

        // третий вариант, тоже плохо
        Quaternion output =
            Quaternion.AngleAxis(_angleRight, Vector3.Cross(transf.right, normal)) *
            Quaternion.AngleAxis(_angleForward, Vector3.Cross(transf.forward, normal)) *
            Quaternion.AngleAxis(transf.eulerAngles.y, normal);

        return output;
    }
 
Последний раз редактировалось Октав 25 авг 2023, 18:22, всего редактировалось 19 раз(а).
Аватара пользователя
Октав
UNIверсал
 
Сообщения: 380
Зарегистрирован: 19 янв 2012, 22:02
Откуда: Красноярский край

Re: Как ограничить тангаж и крен Transform'а

Сообщение 1max1 25 авг 2023, 03:16

Мне всегда хватало чего-то такого:

Синтаксис:
Используется csharp
    Vector3 angles;
       
    void Update()
    {
        angles.x += Input.GetAxis("axis1");
        angles.y += Input.GetAxis("axis2");

        angles.x = Mathf.Clamp(angles.x, -30, 30);
        angles.y = Mathf.Clamp(angles.y, -30, 30);

        transform.eulerAngles = angles;
Аватара пользователя
1max1
Адепт
 
Сообщения: 5505
Зарегистрирован: 28 июн 2017, 10:51

Re: Как ограничить тангаж и крен Transform'а

Сообщение Октав 25 авг 2023, 03:27

1max1 писал(а):Мне всегда хватало чего-то такого:

Синтаксис:
Используется csharp
    Vector3 angles;
       
    void Update()
    {
        angles.x += Input.GetAxis("axis1");
        angles.y += Input.GetAxis("axis2");

        angles.x = Mathf.Clamp(angles.x, -30, 30);
        angles.y = Mathf.Clamp(angles.y, -30, 30);

        transform.eulerAngles = angles;


так вы ограничиваете ввод значений угла, еще и "глобальные" углы ограничиваете.
А мне нужно ограничить уже имеющийся трансформ, который позиционируется самостоятельно.

Дополнил описание темы. а то похоже ее можно неправильно понять
Аватара пользователя
Октав
UNIверсал
 
Сообщения: 380
Зарегистрирован: 19 янв 2012, 22:02
Откуда: Красноярский край


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

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

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