Как получить разницу угла Эйлера от одного положения объекта к другому ориентации

Я хочу найти разницу угла Эйлера (по одной оси) между положением цели относительно ориентации и положения игроков.

Надеюсь, изображение ниже поможет проиллюстрировать то, что я хочу.

Угол Эйлера

То, что я пытался до сих пор, это

    public GameObject player;
    public GameObject target;

    Vector3 targetDir = target.transform.position - player.transform.position;
    float angle = Vector3.Angle(player.transform.forward, targetDir);
    Debug.Log(angle);

Это выведет угол между 0-180, независимо от того, слева он или справа.

Мне нужен угол Эйлера, поэтому угол должен быть от 0 до 360 градусов.

Я попытался преобразовать углы в кватернионы, но получаю противоречивые результаты. Число меняется от очень низкого до высокого при небольшом движении консоли.

var testRotation = Quaternion.FromToRotation(player.transform.forward,target.transform.position - player.transform.position);
Debug.Log(testRotation.eulerAngles.y);

Я пробовал делать это с помощью vector3 и dot

  Vector3 targetDir = player.transform.position - target.transform.position;
    var rot = Mathf.Cos(Vector3.Dot(player.transform.forward, targetDir.normalized));
    Debug.Log(rot);

но это выведет число от 0,5 до 0,999

Используя ответ Draco18s, я создал этот метод (который далек от совершенства). У меня это сработало.

/// <summary>
/// Calculate angle difference on the Y axis between one object (target) and anothers (player) orientation and position as an angle between 0 & 360 degrees
/// </summary>
/// <param name="_target"></param>
/// <param name="_player"></param>
/// <returns></returns>
private float CalcAngle(GameObject _target, GameObject _player)
{
    //Calculate the direction of the target removing any up or down rotation
    Vector3 _newDirection = (new Vector3(_target.transform.position.x, 0, _target.transform.position.z) - new Vector3(_player.transform.position.x, 0, _player.transform.position.z));

    // the vector that we want to measure an angle from
    Vector3 referenceForward = _player.transform.forward;/* some vector that is not Vector3.up */
    // Remove any up or down rotation
    referenceForward = new Vector3(referenceForward.x, 0, referenceForward.z);

    // the vector perpendicular to referenceForward (90 degrees clockwise)
    // (used to determine if angle is positive or negative)
    Vector3 referenceRight = _player.transform.right;
    referenceRight = new Vector3(referenceRight.x, 0, referenceRight.z);

    // Get the angle in degrees between 0 and 180
    float angle = Vector3.Angle(_newDirection, referenceForward);

    // Determine if the degree value should be negative. Here, a positive value
    // from the dot product means that our vector is on the right of the reference vector
    // whereas a negative value means we're on the left.
    float sign = Mathf.Sign(Vector3.Dot(_newDirection, referenceRight));

    // Create an angle between 0-360
    float result = sign * angle;
    if (result < 0)
    {
        result = 360 - Mathf.Abs(result);
    }
    //Give back the result
    return result;
}

Спасибо


person Jim    schedule 05.09.2017    source источник
comment
Вашего метода недостаточно - вы потеряете одну степень свободы (вращение вокруг самого вектора). Преобразуйте углы в кватернионы и переходите оттуда.   -  person meowgoesthedog    schedule 05.09.2017
comment
Я попробовал, возможно, я использую не ту функцию   -  person Jim    schedule 05.09.2017
comment
Вы можете рассчитать угол самостоятельно, выполнив dot(player.forward, targetDir.normalized) math.stackexchange.com/questions/654315/   -  person AresCaelum    schedule 05.09.2017
comment
Привет, я тоже попробовал, но безуспешно   -  person Jim    schedule 05.09.2017
comment
Я считаю, что математика вашего целевого направления неверна, это должно быть target - origin. Диапазон скалярного произведения 2 нормализованных векторов равен -1 - 1   -  person AresCaelum    schedule 05.09.2017
comment
Привет, поменял местами. Это все еще не тот ответ, который мне нужен. Я также ищу, чтобы это было представлено как 0-360 градусов (по одной оси)   -  person Jim    schedule 05.09.2017
comment
Не думаю, что вы правильно сформулировали вопрос. Нет ничего лучше разницы углов Эйлера между позициями (или направлениями?). Вы спрашиваете об одном, двух или трех углах?   -  person Yves Daoust    schedule 05.09.2017
comment
Я прошу один ракурс.   -  person Jim    schedule 06.09.2017


Ответы (1)


Я уверен, что где-то есть цель-обманщик, но я не могу ее найти.

Однако я могу найти код, который я получил ... где-то несколько лет назад, с комментариями.

private float CalcAngle(Vector3 newDirection) {
    // the vector that we want to measure an angle from
    Vector3 referenceForward = transform.forward;/* some vector that is not Vector3.up */

    // the vector perpendicular to referenceForward (90 degrees clockwise)
    // (used to determine if angle is positive or negative)
    Vector3 referenceRight = transform.right;

    // Get the angle in degrees between 0 and 180
    float angle = Vector3.Angle(newDirection, referenceForward);

    // Determine if the degree value should be negative. Here, a positive value
    // from the dot product means that our vector is on the right of the reference vector
    // whereas a negative value means we're on the left.
    float sign = Mathf.Sign(Vector3.Dot(newDirection, referenceRight));

    return sign * angle;
}

Это даст вам значение от -180 до +180. Преобразование этого в 0-360 потребует небольшой математики, но должно быть прямым (подсказка: -179,99 -> +180,01).

person Draco18s no longer trusts SE    schedule 05.09.2017
comment
Спасибо за ответ, метод требует Vector3 'newDirection', не могли бы вы прояснить, что это для меня и как я могу его получить? - person Jim; 06.09.2017
comment
Я предполагаю, что это что-то вроде float angle = CalcAngle (target.transform.position - player.transform.position); Debug.Log (угол); - person Jim; 06.09.2017
comment
@Jim - это вектор, указывающий на цель, направление, в котором вы хотите измерить в. ReferenceForward - это вектор, от которого нужно проводить измерения. Так что да, все правильно. Однако вам, вероятно, следует нормализовать это. - person Draco18s no longer trusts SE; 06.09.2017
comment
Ура @ Draco18s, почему ты предлагаешь мне нормализовать это? - person Jim; 06.09.2017
comment
@Jim Поскольку это вектор направления: вам не нужно сохранять величину. Кроме того, я не уверен, что математика может работать неправильно с ненормализованным вектором. Прошло 3 или 4 года с тех пор, как я испортил проект, из которого взял это. - person Draco18s no longer trusts SE; 06.09.2017