Wann sollte ich Velocity versus AddForce verwenden, wenn ich mit Player-Objekten arbeite?

17

Ich bin verwirrt über diese beiden Methoden im Unity-Framework. Beide bewirken, dass sich das Spielerobjekt bewegt, anhält, die Richtung ändert usw. Wann sollte eines über dem anderen verwendet werden und wann ist eines angemessen?

Robert
quelle
Verknüpft mit: gamedev.stackexchange.com/questions/118711/…
MichaelHouse
@ Byte56 Beide Fragen stellen unterschiedliche Fragen
Robert
1
Anders, aber verwandt. Deshalb sind sie nur verlinkt und keine Duplikate. Show it wird in der verknüpften Spalte rechts angezeigt.
MichaelHouse

Antworten:

13

Sie können velocitydas Objekt mit einer konstanten Geschwindigkeit bewegen (z. B. eine Kugel) und AddForce()Bewegungen hinzufügen (z. B. ein Raumschiff-Triebwerk). Beachten Sie auch, dass es zwei "Arten" von Bewegungen gibt. Kraft und Impuls. Für ein Raumschiff-Triebwerk würden Sie Impuls verwenden.

trojanfoe
quelle
4
Können Sie beschreiben, warum Sie Impulse für ein Raumschiffstrahlruder bevorzugen würden? Dies kann tatsächlich eine nicht ideale Anpassung sein, wenn Sie eine allmähliche Beschleunigung im Laufe der Zeit anwenden, anstatt eine sofortige Änderung des Impulses aufgrund von Dingen wie Waffenstößen. Wird es über ein Zeitfenster angewendet, sollten Sie im Allgemeinen Kraft (oder Beschleunigung, wenn Sie nicht möchten, dass die Masse ein Faktor ist) und sofort Impuls (oder entsprechend VelocityChange) verwenden.
DMGregory
@DMGregory Ja, es hängt von der Art der Kraft ab, die Sie hinzufügen möchten. In meinem Beispiel für das Raumschiff-Triebwerk, bei dem es sich um einen kurzen Energieschub handelt, ist der Impuls die richtige Wahl.
Trojanfoe
2
Es war nicht sofort klar, ob Sie ein kurzes Abfeuern eines Jet oder das kontinuierliche Brennen eines Haupttriebwerks meinten ("Thruster" wird manchmal etwas allgemein in Science-Fiction verwendet), daher dachte ich, ich sollte klarstellen, ob es jemand versuchen sollte mit Impulsen für einen Raketen-Booster. ;)
DMGregory
@DMGregory In der Tat; Meine Space-Tech-Terminologie basiert größtenteils auf Filmen :)
Trojanfoe
@trojanfoe Geh und spiele KSP. Wie jetzt.
user253751
20

Obwohl es bereits eine akzeptierte Antwort gibt, denke ich, dass es einige zusätzliche Details gibt, die es wert sind, behandelt zu werden.

Velocity verwenden

Wenn Sie die Geschwindigkeit einstellen, setzen Sie absolut alles außer Kraft, was die Bewegung des Objekts beeinflussen könnte. In einigen Situationen ist dies wünschenswert, z. B. wenn Sie die Anfangsgeschwindigkeit einer Kugel einmalig einstellen, wenn sie abgefeuert wird, wie im Beispiel von Trojanfoe. Seien Sie nur vorsichtig, denn wenn es in den falschen Situationen verwendet wird, kann es Probleme verursachen:

  • Wenn mehrere Quellen / Skripte versuchen, die Geschwindigkeit desselben Rigidbody durch direktes Einstellen (dh body.velocity = foo) zu ändern , gewinnt derjenige, der zuletzt ausgeführt wurde, und die anderen haben keine Auswirkung. Dies kann dazu führen, dass Fehler in der Reihenfolge der Aktualisierung auftreten, was insbesondere dazu führt, dass Entitäten langsam schweben oder fallen (da die Abwärtsbeschleunigung aufgrund der Schwerkraft außer Kraft gesetzt wird, bevor sie sich ansammeln kann).

  • Wenn Sie die Geschwindigkeit für jedes Bild einstellen, können Kollisionen mit anderen Objekten etwas seltsam sein. Es ist, als würde Ihr Objekt von einem Motor mit unbegrenztem Drehmoment angetrieben - unabhängig davon, wie viel Geschwindigkeit es beim Aufprall verliert, wird es beim nächsten physikalischen Schritt wieder auf Höchstgeschwindigkeit gebracht und seine Geschwindigkeit wird nicht vom Aufprall abgelenkt . Dies kann dazu führen, dass Objekte gestartet werden, mit denen Sie kollidieren, oder dass kleine Objekte in der Lage sind, große Objekte viel leichter zu schieben, als es den Anschein hat, oder dass Objekte langsam an statischen Barrieren entlang gleiten, anstatt sich von ihnen weg / entlang zu lenken.

Diese beiden Effekte können manchmal erwünscht sein. Wenn ich beispielsweise Kinect-Spiele mache und die Gliedmaßen des virtuellen Avatars des Spielers mit der Physikszene interagieren sollen, bewege ich diese Körper normalerweise mit der direkten Geschwindigkeitseinstellung. Da sich die tatsächliche Hand des Spielers an einem bekannten Ort befindet und die Kollision mit diesem virtuellen Objekt nicht verlangsamt wurde, muss die virtuelle Hand dasselbe tun, um in Ausrichtung zu bleiben. In diesem Fall möchten wir also alle anderen physikalischen Effekte überschreiben Bring es hin.

AddForce und Freunde

Im Gegensatz dazu arbeiten AddForce und ähnliche Hilfsfunktionen mit allen anderen Vorgängen in der Physik zusammen. Wenn mehrere Quellen / Skripte AddForce zu einem Rigidbody hinzugefügt werden, werden alle diese Effekte addiert, um eine Nettoveränderung in der Bewegung des Objekts zu erzeugen (die abhängig von der Berechnung auch unabhängig von der Reihenfolge sein kann). Auf diese Weise wird vermieden, dass ein Skript einen anderen Effekt der Physik vollständig unterdrückt.

AddForce gibt es in vier Varianten , indem Sie den optionalen ForceMode-Parameter angeben , der für verschiedene Dinge nützlich ist:

ForceMode       |   Use
-----------------------------------------------------------------------
Force (default) |   Accelerate an object over 1 time step, based on its mass.
                |   Units: Newtons = kg * m/s^2
                |
Acceleration    |   Accelerate an object over 1 time step, ignoring its mass. (like gravity)
                |   Units: m/s^2
                |
Impulse         |   Instantaneously propel an object, based on its mass
                |   Units: N * s = kg * m/s
                |
VelocityChange  |   Instantaneously propel an object, ignoring its mass
                |   (like body.velocity = foo, except multiple scripts can stack)
                |   Units:  m/s

Wenn Sie versuchen, eine kontinuierliche Push-over-Zeit (z. B. etwas, das Sie bei jedem FixedUpdate anwenden) zu modellieren, wie z. B. ein Autofahren oder eine Rakete, die brennt, oder eine Schwerkraft, die gut zieht, möchten Sie Kraft oder Beschleunigung. (Abhängig davon, ob schwere Objekte langsamer beschleunigen sollen)

Wenn Sie eine plötzliche, scharfe Änderung der Bewegung modellieren, z. B. eine Kugel abfeuern, sich von einer Explosion zurückziehen oder von einer Barriere abprallen, möchten Sie mit größerer Wahrscheinlichkeit Impulse oder VelocityChange.

Die Verwendung von AddForce hilft Ihnen dabei, mehr physischen Realismus zu erreichen. Es kann jedoch auch erforderlich sein, dass Sie sich mehr mit der Physik Ihres Verhaltens befassen. Wenn Sie beispielsweise möchten, dass Ihr Körper eine endliche Beschleunigung bis zu einer Zielgeschwindigkeit aufweist, damit er realistischer auf Kollisionen reagiert, als wenn Sie die Geschwindigkeit in jedem Frame einstellen, möchten Sie wahrscheinlich eine Berechnung ähnlich der folgenden Hilfsfunktion:

public static void AccelerateTo(this Rigidbody body, Vector3 targetVelocity, float maxAccel)
{
    Vector3 deltaV = targetVelocity - body.velocity;
    Vector3 accel = deltaV/Time.deltaTime;

    if(accel.sqrMagnitude > maxAccel * maxAccel)
        accel = accel.normalized * maxAccel;

    body.AddForce(accel, ForceMode.Acceleration);
}

Der Grund, warum ich all diese "Hilfsfunktionen" nenne, ist, dass Sie technisch gesehen alle dieselben Ziele erreichen können mit:

 body.velocity += suitablyCalculatedDeltaV;

( Ich denke . Es ist möglich, dass Unitys PhysX / Box2D-basierte Physiklöser Änderungen über AddForce separat puffern, aber ich habe keine offensichtlichen Konsequenzen davon gesehen.)

Letztendlich erhalten wir also durch diese Funktionen wirklich klare Absichten . Wenn ich eine allmähliche Kraft anwenden möchte, muss ich nicht daran denken, mein deltaV mit Time.deltaTime zu multiplizieren und durch Masse zu dividieren. Ich möchte nur ForceMode.Force und es wird korrekt und konsistent gehandhabt. Und wenn ich oder jemand anderes später auf meinen Code zurückgreift, ist sofort klar, was ich meinte, ohne dass ich die Zeit- und Massenberechnungen entschlüsseln muss, um es herauszufinden.

DMGregory
quelle
6

Zusätzlich zu Trojanfoes Antwort Angry Birds vs Car Racing. Zwei wichtige und unterschiedliche Beispiele dieser Verfahren ( AddForceund velocityjeweils). In Angry Birds ist die Verwendung der Geschwindigkeit beispielsweise etwas schwieriger, da Sie die Flugbahn des Projektils selbst festlegen müssten, wie z.

Wenn ich AddForce in Angry Birds benutze, würde ich verwenden,

_birdRigidbody.AddForce(new Vector2(5,5));

Während, wenn ich Geschwindigkeit dann benutze, ich Flugbahn handhaben würde, die verwendet

x = v*t*Cos(theta) y = v*t*Sin(theta) - 0.5 * g * t *t

Oder sowas.

Während des Rennspiels müsstest du die Geschwindigkeit ständig kontrollieren, nicht wie bei Angry Birds, dh Shoot and all. In diesem Szenario ist das Handle velocityalso nützlicher als AddForce.

Ich hoffe du verstehst. Zumindest ein bisschen.

Hamza Hasan
quelle
1
Ihr AngryBirds-Beispiel sollte wahrscheinlich eine sofortige Änderung des Impulses (z. B. Impulse oder VelocityChange) verwenden, wenn die Schleuder losgelassen wird, und nicht die standardmäßige ForceMode.Force, die ihren Effekt über ein Zeitfenster simuliert. Sie können die Zahlen so abstimmen, dass bei beiden Ansätzen ein gleichwertiges Verhalten erzielt wird. Wenn Sie jedoch Ihren festen Zeitschritt ändern, hat die Kraftlösung eine andere Ausgabe (da die Kraft über einen längeren oder kürzeren Zeitraum integriert wird), während der Impuls wie folgt konsistent bleibt erwünscht, weil es nur den Moment der Veröffentlichung darstellt.
DMGregory
0

Rigidbody Velocity und Rigidbody Addforce sind zwei verwirrende Funktionen in Unity 3D, und Anfänger verstehen häufig ihren Unterschied nicht. In diesem Artikel werden wir den Unterschied zwischen RigidBody.velocity und RigidBody.addforce diskutieren.

In beiden Fällen, egal ob es sich um Addforce- oder Velocity-Funktion handelt, werden wir den Begriff Force verwenden, um sie zu erklären.

Wenn wir Rigidbody.velocity verwenden, fügen wir in diesem Fall unserem Objekt Kraft hinzu, aber diese Kraft bewegt das Objekt nur, wenn und bis wir weiterhin Kraft anwenden.

Beispielsweise

body.velocity = new Vector3 (0,0,5);

Angenommen, Sie haben 5f in z-Position hinzugefügt und diese Kraft wird hinzugefügt, wenn Sie die W-Taste drücken. Wenn Sie also die W-Taste drücken, startet das Objekt sofort mit der Geschwindigkeit von 5. Wenn Sie diese Funktion für ein Auto verwenden, wird das Auto mit der Geschwindigkeit von 5 gestartet.

body.velocity = new Vector3 (0,0,200);

Und wenn Sie sagen, ändern Sie den Wert auf 200 und drücken Sie nach dem Speichern die Taste W. Das Auto startet mit einer Geschwindigkeit von 200, die in der realen Welt nicht möglich ist.

Wenn Sie jetzt über Rigidbody.addforce sprechen

Indem wir unser Auto-Beispiel fortsetzen. wenn Sie die Kraft von 200 zum Auto addieren

body.addforce (0,0.200);

Das Auto startet nicht mit der Geschwindigkeit von 200, wenn wir W drücken. Es startet jedoch langsam, erhöht dann seine Geschwindigkeit und stoppt entsprechend dem Wert von Drag.

Rigidbody.addforce startet langsam und beschleunigt dann, genau wie Sie einen schweren Tisch ziehen. Zuerst werden Sie diesen Tisch schieben. Der Tisch bewegt sich nur ein wenig von seiner Position weg, aber wenn Sie diesen Tisch weiter schieben, beginnt er sich zu bewegen. Wenn Sie diesen Tisch verlassen, legt er je nach Oberfläche eine gewisse Strecke zurück und das ist derselbe starre Körper.

Sie können Rigidbody.velocity verwenden, um Ihr Objekt so zu bewegen, dass es sofort wie ein Spielersprung reagiert. Das Ergebnis dieser Kraft verschwindet unmittelbar nach dem Sprung. Sie können Rigidbody.addforce verwenden, wenn Sie einen langsamen Start und dann eine kontinuierliche Bewegung benötigen Eine Rakete. Wenn Sie im Sprung Rigidbody.addforce verwenden, bleibt der Spieler / das Objekt eine Weile im Raum und kehrt dann zum Boden zurück.

(Quelle)

Numan Hamza
quelle
Sie sollten zumindest versuchen, Ihren Beitrag an das Format einer Stack Exchange-Antwort anzupassen :)
Vaillancourt