Ich versuche, ein Objekt auf ein Ziel zu starten, angesichts seiner Position, seiner Zielposition, der Startgeschwindigkeit und der Schwerkraft. Ich folge dieser Formel aus Wikipedia :
Ich habe den Code nach besten Kräften vereinfacht, kann das Ziel aber immer noch nicht konsequent treffen. Ich betrachte nur die größere Flugbahn der beiden, die aus der + - Auswahl in der Formel verfügbar sind.
Weiß jemand was ich falsch mache?
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;
}
}
Antworten:
Ich bin etwas skeptisch gegenüber
atan
hier, da das Tangentenverhältnis in bestimmten Winkeln ins Unendliche abschießt und zu numerischen Fehlern führen kann (auch außerhalb des undefinierten / durch Null dividierten Falls für direktes Auf / Ab-Schießen).Mit den in dieser Antwort erarbeiteten Formeln können wir dies anhand der (anfangs unbekannten) Zeit bis zum Aufprall
T
anhand der Initialespeed
des Projektils parametrisieren :Sie können entweder T_min oder T_max wählen (oder etwas dazwischen, wenn Sie mit Geschwindigkeiten bis zu einem Maximum feuern möchten, das jedoch nicht unbedingt einem Maximum entspricht).
(
T_min
ist die flache rote Flugbahn unten undT_max
Ist die hohe grüne. Jede Flugbahn zwischen ihnen ist mit einer möglichen Geschwindigkeit realisierbar. Wenn die beiden in die gelbe Flugbahn übergehen, befindet sich das Objekt außerhalb der Reichweite.)Nachdem wir einen Wert für berechnet haben
T
, ist der Rest einfach:Sie können diese Geschwindigkeit direkt verwenden (sie hat eine Länge, die
speed
der Konstruktion entspricht), oder wenn Sie den Winkel wirklich kennen müssen, können Sie sie verwendenatan2(vy, vx)
Bearbeiten: Um dies auf weitere Fälle anzuwenden, ist hier eine 3D-Version:
quelle
discRoot
ist die Quadratwurzel der Diskriminante , dh der Teil, der in der quadratischen Formel unter dem Quadratwurzelzeichen erscheint .b
ist das -1-fache der Variablen b in der quadratischen Formel. Leider kenne ich keinen aussagekräftigeren Namen dafür. (Ich habe es mit -1 multipliziert, als ich die späteren Schritte zugewiesen habe, da das führende Minus bereits eingebrannt ist und die Quadrierung nicht beeinflusst.) Siehe die andere Antwort für eine vollständige Ableitung, obwohl ein paar Quadrate fehlen (wird in KürzeDank DMGregory habe ich jetzt ein C # -Erweiterungsskript, das dafür verwendet werden kann. Die neueste Version finden Sie auf GitHub .
quelle
Persönlich würde ich mir nicht einmal die Mühe machen, irgendeine komplizierte Formel zu verwenden.
Es schießt es einfach in Richtung des Ziels. Wenn Sie die Schwerkraft, die Entfernung usw. kompensieren möchten, stellen Sie
someSortOfMultiplier()
eine Funktion ein, die einen Float zurückgibt, der bei Multiplikation mit dem obigen Code kompensiert.quelle