Quando dovrei usare la velocità contro addForce quando ho a che fare con gli oggetti giocatore?


18

Sono confuso su questi due metodi nel framework Unity. Entrambi fanno muovere, fermare, cambiare direzione l'oggetto del giocatore, ecc. Quando si dovrebbe usare uno sopra l'altro e quando è appropriato?



@ Byte56 entrambe le domande si pongono su cose diverse
Robert,

1
Diverso, ma correlato. Ecco perché sono solo collegati e non duplicati. Mostra viene visualizzato nella colonna collegata a destra.
MichaelHouse

Risposte:


13

Utilizzeresti velocityper spostare l'oggetto a velocità costante (ad esempio un proiettile) e AddForce()per aggiungere movimento (ad esempio un propulsore di astronave). Si noti inoltre che esistono due "tipi" di movimento; forza e impulso. Per una navicella spaziale propulsore usereste impulso.


4
Puoi descrivere perché preferiresti gli impulsi per un propulsore di astronave? Questo potrebbe effettivamente essere un adattamento non ideale se stai applicando un'accelerazione graduale nel tempo, piuttosto che cambiamenti istantanei nel momento dovuti a cose come gli impatti delle armi. Applicato in una finestra temporale in genere vorrai forza (o accelerazione se non vuoi che la massa sia un fattore) mentre istantaneamente utilizzeresti impulso (o, di conseguenza, velocityChange)
DMGregory

@DMGregory Sì, dipende dal tipo di forza che vuoi aggiungere. Nel mio esempio del propulsore di astronave, che è un momentaneo scoppio di energia, allora l'impulso è la scelta corretta.
Trojanfoe,

2
Non è stato subito chiaro se si intendesse un breve lancio di un jet d'assetto o la bruciatura continua di un motore principale (il "propulsore" è usato un po 'genericamente a volte in fantascienza), quindi ho pensato che avrei dovuto chiarire per non provare qualcuno usando gli impulsi per un razzo. ;)
DMGregory

@DMGregory Infatti; la mia terminologia di tecnologia spaziale si basa in gran parte sui film :)
trojanfoe,

@trojanfoe Go gioca a KSP. Come adesso.
user253751

21

Anche se c'è già una risposta accettata, penso che ci siano alcuni dettagli aggiuntivi che vale la pena trattare.

Usando la velocità

Quando imposti la velocità, hai la precedenza su tutto ciò che potrebbe influenzare il movimento di quell'oggetto. In alcune situazioni questo è desiderabile, come impostare la velocità iniziale di un proiettile una volta nel momento in cui viene sparato, come nell'esempio di trojanfoe. Fai attenzione, perché se usato in situazioni sbagliate può causare problemi:

  • Se più fonti / script tentano di modificare la stessa velocità del Rigidbody impostandola direttamente (ad es. body.velocity = foo), Allora l'ultima corsa vince e le altre hanno effetto zero. Questo può portare all'ordine dei bug di aggiornamento, in particolare facendo sì che le entità si librino o cadano lentamente (perché l'accelerazione verso il basso dovuta alla gravità viene ignorata prima che possa accumularsi)

  • Se stai impostando la velocità su ogni fotogramma, le collisioni con altri oggetti possono essere un po 'strane. È come se il tuo oggetto venisse azionato da un motore con coppia infinita - non importa quanta velocità perde in caso di impatto, torna alla massima velocità nel passo fisico successivo e la sua velocità non viene deviata dall'impatto . Questo può portare al lancio di oggetti con cui ti scontri, o a piccoli oggetti che riescono a spingere quelli enormi molto più facilmente di quanto sembri, o oggetti che scivolano lentamente lungo le barriere statiche invece di deviare via / lungo di essi.

Entrambi questi effetti possono essere desiderati a volte. Ad esempio, quando realizzo giochi Kinect e voglio che gli arti dell'avatar virtuale del giocatore siano in grado di interagire con la scena fisica, di solito muovo quei corpi usando l'impostazione della velocità diretta. Poiché la mano reale del giocatore si trova in un luogo noto e non ha rallentato dalla collisione con quell'oggetto virtuale, la sua mano virtuale deve fare lo stesso per rimanere in allineamento, quindi in questo caso in realtà vogliamo scavalcare tutti gli altri effetti fisici per ottenerlo lì.

AddForce and Friends

AddForce e simili funzioni di supporto, al contrario, sono fatte per cooperare con tutto ciò che accade nel mondo della fisica. Se più fonti / script si aggiungono a un corpo rigido, tutti questi effetti vengono sommati per creare una variazione netta nel movimento dell'oggetto (che, a seconda di come viene calcolato, può anche essere indipendente dall'ordine). Questo aiuta a evitare che uno script calpesti completamente qualche altro effetto fisico.

AddForce è disponibile in quattro versioni specificando il parametro ForceMode opzionale , che sono utili per cose diverse:

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

Se stai cercando di modellare una spinta continua nel tempo (ad es. Qualcosa che stai applicando ad ogni FixedUpdate), come una macchina che guida o un razzo che brucia o un pozzo a gravità che tira, vuoi Forza o Accelerazione. (A seconda se si desidera che gli oggetti pesanti accelerino più lentamente)

Se stai modellando un improvviso e brusco cambiamento di movimento, come sparare un proiettile, indietreggiare da un'esplosione o far rimbalzare una barriera, probabilmente vorrai Impulse o VelocityChange.

L'uso di AddForce ti aiuta a ottenere più realismo fisico, ma può anche richiedere di dedicare più tempo a pensare attraverso la fisica del tuo comportamento. Ad esempio, se vuoi che il tuo corpo abbia un'accelerazione finita fino a una velocità target, in modo che reagisca più realisticamente alle collisioni rispetto all'impostazione della velocità in ogni fotogramma, probabilmente vorrai un calcolo simile a questa funzione di supporto:

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);
}

Il motivo per cui chiamo tutte queste "funzioni di supporto" è che tecnicamente potresti raggiungere tutti gli stessi obiettivi con:

 body.velocity += suitablyCalculatedDeltaV;

( Penso . È possibile che i risolutori del buffer di Unity basati su PhysX / Box2D risolvano le modifiche tramite AddForce separatamente, ma non ne ho visto ovvie conseguenze)

Quindi, alla fine della giornata, ciò che queste funzioni ci danno davvero è la chiarezza delle intenzioni . Quando voglio applicare una forza graduale, non ho bisogno di ricordare di moltiplicare il mio deltaV per Time.deltaTime e dividere per massa, dico solo che voglio ForceMode.Force ed è gestito in modo corretto e coerente. E quando io o qualcun altro arriviamo a ripetere il mio codice in un secondo momento, è immediatamente chiaro cosa intendevo dire, senza dover decodificare i calcoli di tempo e di massa per capirlo.


6

Oltre alla risposta di Trojanfoe , Angry Birds vs Car Racing. Due esempi principali e diversi di questi metodi ( AddForcee velocityrispettivamente). Ad esempio, in Angry Birds l'uso della velocità è un po 'più difficile in quanto dovresti impostare la traiettoria del proiettile da solo, come,

Quando uso AddForce in Angry Birds, vorrei usare,

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

Mentre quando uso la velocità, gestisco la traiettoria usando

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

O qualcosa del genere.

Mentre nel gioco Car Racing dovresti controllare sempre la velocità, non come Angry Birds, ovvero Spara e tutto il resto. Quindi in quello scenario l'handle velocityè più utile di AddForce.

Spero che tu capisca. Almeno un pochino.


1
L'esempio di AngryBirds dovrebbe probabilmente utilizzare una variazione istantanea del momento (ad es. Impulse o VelocityChange) quando viene rilasciata la fionda, anziché il ForceMode predefinito. Forza che simula il suo effetto in una finestra temporale. È possibile ottimizzare i numeri per ottenere un comportamento equivalente da uno dei due approcci, ma se si modifica il passo del tempo fisso la soluzione della forza avrà un output diverso (poiché integra la forza su un intervallo di tempo più lungo o più breve) mentre l'impulso rimane coerente come desiderato, perché rappresenta solo il momento del rilascio.
DMGregory

0

Rigidbody Velocity e Rigidbody Addforce sono due funzioni confuse in Unity 3D e spesso i principianti non riescono a capire la loro differenza. In questo articolo discuteremo della differenza tra RigidBody.velocity e RigidBody.addforce.

In entrambi i casi, sia che si tratti di Addforce o della funzione di velocità, useremo il termine forza per spiegarli.

Quando stiamo usando Rigidbody.velocity, quindi, in quel caso, stiamo aggiungendo forza al nostro oggetto, ma questa forza sposta l'oggetto solo a meno che e finché non continuiamo ad applicare la forza.

Per esempio

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

Supponiamo che tu abbia aggiunto 5f in posizione z e che forza verrà aggiunta quando premi il tasto W. Quindi quando premi il tasto W l'oggetto si avvierà istantaneamente alla velocità di 5. È lo stesso se aggiungi forza usando questa funzione su un'auto, quell'auto inizierà alla velocità di 5.

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

E se lasci dire cambiare il valore in 200 e poi dopo aver salvato premi W. L'auto inizierà a funzionare alla velocità di 200 dall'inizio, cosa impossibile nel mondo reale.

Ora, se parli di Rigidbody.addforce

Continuando il nostro esempio di auto. se aggiungi la forza di 200 all'auto

body.addforce (0,0,200);

L'auto non inizierà a muoversi alla velocità di 200 se si preme W ma parte da lenta e quindi aumenta le sue velocità e si arresta in base al valore di trascinamento.

Rigidbody.addforce inizia lentamente e poi accelera, proprio come se trascini un tavolo pesante, prima inizi a spingere quel tavolo, il tavolo si sposterà un po 'dalla sua posizione ma se continui a spingere quel tavolo inizierà a muoversi e se lasci quel tavolo coprirà una certa distanza a seconda della superficie e questo è lo stesso rigido.

Puoi usare Rigidbody.velocity dove vuoi solo spostare il tuo oggetto per reagire istantaneamente come il salto del giocatore e il risultato di quella forza svanirà subito dopo il salto e puoi usare Rigidbody.addforce dove hai bisogno di un avvio lento e quindi il movimento continuo come un razzo. Se usi Rigidbody.addforce nel salto, Player / Object rimarrà nello spazio per un po 'e poi tornerà a terra.

(fonte)


Dovresti almeno provare ad adattare il tuo post al formato di una risposta di Stack Exchange :)
Vaillancourt
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.