Блог программиста
Математика Unity (Урок 3). Mathf арксинус и арккосинус.
03.07.2013Математика Unity

Синус и косинус были рассмотрены в первом уроке. В этом уроке мы рассмотрим обратные функции синуса и косинуса — арксинус и арккосинус. Полные определения можно прочитать в справочнике, учебнике или энциклопедии. Я их немного изменил:

Арксинус числа k (-1 <= k <= 1) – значение угла a в диапазоне от -90 до 90 градусов, синус которого равен k. Арккосинус числа k (-1 <= k <= 1) – значение угла a в диапазоне от 0 до 180 градусов, косинус которого равен k.
Для простоты понимания диапазоны я указал в градусах, хотя принято значение углов считать в радианах.
В Unity (C#) арксинус и арккосинус вычисляются функциями (угол исчисляется в радианах):
float Angle = Mathf.Asin(float Sin)			//Арксинус
float Angle = Mathf.Acos(float Cos)			//Арккосинус

Применение в игре.

Имеется:
  1. Игрок, который гуляет по территории секретной базы.
  2. Охранник, которому не нравиться, что кто-то на его территории.
Благодаря системе датчиков, расположенных на всей территории, охранник знает точное местоположение игрока.

Чтобы схватить игрока, охраннику необходимо до него добежать. Чтобы охранник побежал по самому короткому пути, надо его повернуть к игроку лицом. Тут нам и помогут арксинус с арккосинус.
Но откуда нам знать синус и косинус угла, на который надо повернуть охранника?
Координаты игрока относительно охранника — это и есть синус и косинус!
Напишем небольшой код для поворота охранника:
using UnityEngine;
public class RotateSecurity : MonoBehaviour {
     
    //Трансформ игрока, который передают датчики
    public Transform player;
     
    // Update is called once per frame
    void Update ()
    {
	//Если позиция игрока неизвестна, ничего не делаем
        if(player == null) return;
	//Получаем нормализованный вектор позиции игрока, чтобы синуc и косинуc были в диапазоне от -1 до 1.
        Vector3 normPos = player.position.normalized;   
	//Получаем значение угла и переводим его в градусы
        float Angle = Mathf.Acos(normPos.z) * Mathf.Rad2Deg;
	//Поворачиваем охранника в нужном направлении
        transform.Rotate(Vector3.up, Angle - transform.rotation.eulerAngles.y);
    }
}

Охранник прекрасно поворачивается.
А что если игрок с другой стороны?

Тогда охранник повернётся не туда, так как арккосинус возвращает значение угла в диапазоне от 0 до 180 градусов.
И тут нам опять помогут знаки, только уже не косинуса и не тангенса, а синуса.


А, Г - отрицательный.
Б, В - положительный.

Всё очень просто. Если синус меньше нуля, то умножаем значение угла на противоположное (домножаем на -1).
Улучшенный код:
using UnityEngine;
public class RotateSecurity : MonoBehaviour {
    
    public Transform player;           
     
    // Update is called once per frame
    void Update ()
    {
        if(player == null) return;     
        Vector3 normPos = player.position.normalized;  
        float Angle = Mathf.Acos(normPos.z) * Mathf.Rad2Deg;
	//Если синуc отрицательный...
        if(normPos.x < 0)
        {
	    //Меняем угол на противоположный
            Angle = -Angle;
        }
        transform.Rotate(Vector3.up, Angle - transform.rotation.eulerAngles.y);
    }
}

В место арксинуса можно использовать арккосинус, но в этом случае меняется диапазон и всё немного усложняется. Приводить пример не буду, разберёте самостоятельно.

Тут урок и закончился.
P.S. Если что-то не понятно, пишите в комментариях.

8869