J'essaie de lancer un objet sur une cible, étant donné sa position, sa position cible, la vitesse de lancement et la gravité. Je suis cette formule de Wikipedia :
J'ai simplifié le code au mieux de mes capacités, mais je ne parviens toujours pas à atteindre la cible de manière cohérente. Je ne considère que la trajectoire plus haute, des deux disponibles à partir du choix + - dans la formule.
Est-ce que quelqu'un sait ce que je fais mal?
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;
}
}
Réponses:
Je suis un peu sceptique quant à l'utilisation
atan
ici, car le rapport de tangence se déclenche à l'infini sous certains angles, et peut conduire à des erreurs numériques (même en dehors de l'indéfini / diviser par zéro pour la prise de vue droite / haute).En utilisant les formules élaborées dans cette réponse , nous pouvons paramétrer cela en termes de temps (initialement inconnu) pour l'impact,
T
en utilisant l'initialespeed
du projectile:Vous pouvez choisir T_min ou T_max (ou quelque chose entre les deux si vous souhaitez tirer avec des vitesses allant jusqu'à mais pas nécessairement égales à un certain maximum)
(
T_min
est la trajectoire rouge peu profonde en bas, etT_max
est la grande verte. Toute trajectoire entre eux est viable à une vitesse réalisable. Lorsque les deux fusionnent dans la trajectoire jaune, l'objet est hors de portée.)Maintenant que nous avons calculé une valeur pour
T
, le reste est simple:Vous pouvez utiliser cette vitesse directement (elle a une longueur égale à
speed
par construction), ou si vous avez vraiment besoin de connaître l'angle, vous pouvez utiliseratan2(vy, vx)
Edit: pour rendre cela applicable à plus de cas, voici une version 3D:
la source
discRoot
est la racine carrée du discriminant , qui est la partie qui apparaît sous le signe racine carrée dans la formule quadratique .b
est -1 fois la variable b dans la formule quadratique. Malheureusement, je ne connais pas de nom plus descriptif. (Je l'ai multiplié par -1 lors de l'affectation pour nettoyer les étapes ultérieures, car le moins en tête est déjà intégré et n'affecte pas la quadrature). Voir l'autre réponse pour une dérivation complète, bien qu'il manque quelques carrés (corrigera sous peu)Grâce à DMGregory, j'ai maintenant un script d'extension C # qui peut être utilisé pour cela. La version la plus récente peut être trouvée sur GitHub .
la source
Personnellement, je ne prendrais même pas la peine d'utiliser n'importe quel type de formule compliquée.
Il tire simplement dans la direction de la cible. Et si vous souhaitez compenser la gravité, la distance, etc., définissez
someSortOfMultiplier()
une fonction qui renvoie un flotteur qui compensera une fois multiplié avec le code ci-dessus.la source