Я пытаюсь запустить объект по цели, учитывая его положение, положение цели, скорость запуска и гравитацию. Я следую этой формуле из Википедии :
Я максимально упростил код, но до сих пор не могу последовательно достичь цели. Я рассматриваю только более высокую траекторию из двух, доступных из + - выбора в формуле.
Кто-нибудь знает, что я делаю не так?
using UnityEngine;
public class Launcher : MonoBehaviour
{
public float speed = 10.0f;
void Start()
{
Launch(GameObject.Find("Target").transform);
}
public void Launch(Transform target)
{
float angle = GetAngle(transform.position, target.position, speed, -Physics2D.gravity.y);
var forceToAdd = new Vector2(Mathf.Cos(angle), Mathf.Sin(angle)) * speed;
GetComponent<Rigidbody2D>().AddForce(forceToAdd, ForceMode2D.Impulse);
}
private float GetAngle(Vector2 origin, Vector2 destination, float speed, float gravity)
{
float angle = 0.0f;
//Labeling variables to match formula
float x = Mathf.Abs(destination.x - origin.x);
float y = Mathf.Abs(destination.y - origin.y);
float v = speed;
float g = gravity;
//Formula seen above
float valueToBeSquareRooted = Mathf.Pow(v, 4) - g * (g * Mathf.Pow(x, 2) + 2 * y * Mathf.Pow(v, 2));
if (valueToBeSquareRooted >= 0)
{
angle = Mathf.Atan((Mathf.Pow(v, 2) + Mathf.Sqrt(valueToBeSquareRooted)) / g * x);
}
else
{
//Destination is out of range
}
return angle;
}
}
Ответы:
Я немного скептически отношусь к использованию
atan
здесь, потому что отношение тангенсов отходит к бесконечности под определенными углами и может привести к ошибкам чисел (даже за пределами неопределенного случая / деления на ноль для стрельбы прямо вверх / вниз).Используя формулы, разработанные в этом ответе , мы можем параметризовать это с точки зрения (первоначально неизвестного) времени воздействия
T
, используя начальнуюspeed
часть снаряда:Вы можете выбрать либо T_min, либо T_max (или что-то промежуточное, если вы хотите стрелять со скоростями до, но не обязательно равными некоторому максимуму)
(
T_min
это мелкая красная траектория внизу иT_max
высокая зеленая траектория. Любая траектория между ними жизнеспособна с некоторой возможной скоростью. Когда эти две сливаются в желтую траекторию, объект находится вне диапазона.)Теперь, когда мы вычислили значение для
T
, все остальное просто:Вы можете использовать эту скорость напрямую (она имеет длину, равную
speed
конструкции), или если вам действительно нужно знать угол, вы можете использоватьatan2(vy, vx)
Изменить: чтобы сделать это применимо к большему количеству случаев, вот 3D-версия:
источник
discRoot
- это квадратный корень дискриминанта , который является частью, которая появляется под знаком квадратного корня в квадратной формуле .b
в -1 раз превышает переменную b в квадратной формуле. К сожалению, я не знаю более описательного названия для этого. (Я умножил его на -1 при назначении на более поздние шаги, так как ведущий минус уже запечен и не влияет на квадрат). Смотрите другой ответ для полного вывода, хотя пара квадратов отсутствует (будет исправлено в ближайшее время)Благодаря DMGregory у меня теперь есть скрипт расширения C #, который можно использовать для этого. Самую последнюю версию можно найти на GitHub .
источник
Лично я бы даже не стал использовать какую-либо сложную формулу.
Это просто стреляет в направлении цели. И если вы хотите компенсировать гравитацию, расстояние и т. Д., Установите
someSortOfMultiplier()
функцию, которая возвращает число с плавающей запятой, которое будет компенсировать при умножении на приведенный выше код.источник