Quand dois-je utiliser la vélocité par rapport à addForce lorsque je traite des objets de joueur?

18

Je suis confus au sujet de ces deux méthodes dans le cadre d'Unity. Les deux font bouger, arrêter, changer de direction, etc. quand le joueur doit-il être utilisé et quand est-il approprié?

Robert
la source
@ Byte56, les deux questions demandent des choses différentes
Robert
1
Différent, mais lié. C'est pourquoi ils sont simplement liés et non en double. Le montrer apparaît dans la colonne liée à droite.
MichaelHouse

Réponses:

13

Vous utiliseriez velocitypour déplacer l'objet à un rythme constant (par exemple une balle) et AddForce()pour ajouter du mouvement (par exemple un propulseur de vaisseau spatial). Notez également qu'il existe deux "types" de mouvement; force et impulsion. Pour un propulseur de vaisseau spatial, vous utiliseriez l'impulsion.

trojanfoe
la source
4
Pouvez-vous décrire pourquoi vous préférez les impulsions pour un propulseur de vaisseau spatial? Cela peut en fait être un ajustement non idéal si vous appliquez une accélération progressive au fil du temps, plutôt que des changements instantanés de l'élan dus à des choses comme les impacts d'armes. Appliqué sur une fenêtre de temps, vous aurez généralement besoin de force (ou d'accélération si vous ne voulez pas que la masse soit un facteur) tandis que vous utiliseriez instantanément l'impulsion (ou, en conséquence, velocityChange)
DMGregory
@DMGregory Oui, cela dépend du type de force que vous souhaitez ajouter. Dans mon exemple du propulseur de vaisseau spatial, qui est une explosion d'énergie momentanée, l'impulsion est le bon choix.
trojanfoe
2
Il n'était pas immédiatement clair si vous vouliez dire un court tir d'un jet d'attitude ou la brûlure continue d'un moteur principal (le "propulseur" est parfois utilisé de manière générique en science-fiction), alors j'ai pensé que je devrais clarifier de peur que quelqu'un n'essaye en utilisant des impulsions pour un propulseur de fusée. ;)
DMGregory
@DMGregory En effet; ma terminologie de technologie spatiale est largement basée sur des films :)
trojanfoe
@trojanfoe Allez jouer KSP. Comme maintenant.
user253751
21

Bien qu'il y ait déjà une réponse acceptée, je pense qu'il y a quelques détails supplémentaires qui méritent d'être couverts.

Utilisation de Velocity

Lorsque vous définissez la vitesse, vous remplacez absolument tout ce qui pourrait affecter le mouvement de cet objet. Dans certaines situations, cela est souhaitable, comme le réglage de la vitesse initiale d'une balle une fois au moment où elle est tirée, comme dans l'exemple de trojanfoe. Méfiez-vous, car lorsqu'il est utilisé dans de mauvaises situations, il peut provoquer des problèmes:

  • Si plusieurs sources / scripts essaient de modifier la même vitesse du Rigidbody en la réglant directement (c'est-à-dire body.velocity = foo), alors celui qui s'exécute en dernier gagne et les autres n'ont aucun effet. Cela peut conduire à l'ordre des bogues de mise à jour, en particulier à faire que les entités planent ou tombent lentement (car l'accélération vers le bas due à la gravité est annulée avant de pouvoir s'accumuler)

  • Si vous définissez la vitesse à chaque image, les collisions avec d'autres objets peuvent être un peu étranges. C'est comme si votre objet était propulsé par un moteur avec un couple infini - peu importe la vitesse qu'il perd lors d'un impact, il revient à la vitesse maximale lors de la prochaine étape physique, et sa vitesse n'est pas déviée loin de l'impact . Cela peut conduire à lancer des objets avec lesquels vous entrez en collision, ou à permettre à de petits objets de pousser des objets énormes beaucoup plus facilement qu'il n'y paraît, ou à des objets glissant lentement le long de barrières statiques au lieu de dévier / s'éloigner.

Ces deux effets peuvent parfois être souhaités. Par exemple, lorsque je crée des jeux Kinect et que je souhaite que les membres de l'avatar virtuel du joueur puissent interagir avec la scène physique, je déplace généralement ces corps en utilisant le réglage direct de la vitesse. Parce que la main réelle du joueur est dans un endroit connu et n'a pas ralenti de la collision avec cet objet virtuel, sa main virtuelle doit faire de même pour rester en alignement, donc dans ce cas, nous voulons réellement remplacer tous les autres effets physiques pour y arriver.

AddForce et ses amis

AddForce et les fonctions d'assistance similaires, en revanche, sont conçues pour coopérer avec tout le reste du monde de la physique. Si plusieurs sources / scripts AddForce à un Rigidbody, tous ces effets sont ajoutés ensemble pour créer un changement net dans le mouvement de l'objet (qui, selon la façon dont il est calculé, peut également être indépendant de l'ordre). Cela permet d'éviter qu'un script n'efface complètement un autre effet physique.

AddForce est disponible en quatre versions en spécifiant le paramètre facultatif ForceMode , qui sont utiles pour différentes choses:

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

Si vous essayez de modéliser une poussée continue dans le temps (par exemple, quelque chose que vous appliquez à chaque FixedUpdate), comme une voiture qui roule ou une fusée qui brûle ou une gravité qui tire bien, vous voulez la Force ou l'accélération. (Selon que vous souhaitez que les objets lourds accélèrent plus lentement)

Si vous modélisez un changement brusque et brusque de mouvement, comme le tir d'une balle, le recul d'une explosion ou le rebond d'une barrière, alors vous voudrez probablement Impulse ou VelocityChange.

Utiliser AddForce vous aide à atteindre plus de réalisme physique, mais cela peut également nécessiter que vous passiez plus de temps à réfléchir à la physique de votre comportement. Par exemple, si vous voulez que votre corps ait une accélération finie jusqu'à une vitesse cible, afin qu'il réagisse de manière plus réaliste aux collisions que de définir la vitesse à chaque image, vous voudrez probablement un calcul similaire à cette fonction d'aide:

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

La raison pour laquelle j'appelle toutes ces "fonctions d'assistance" est que, techniquement, vous pouvez atteindre les mêmes fins avec:

 body.velocity += suitablyCalculatedDeltaV;

( Je pense . Il est possible que les tampons des solveurs physiques basés sur PhysX / Box2D d'Unity changent séparément via AddForce, mais je n'en ai pas vu les conséquences évidentes)

Donc, au bout du compte, ce que ces fonctions nous apportent vraiment, c'est la clarté de l'intention . Quand je veux appliquer une force graduelle, je n'ai pas besoin de me rappeler de multiplier mon deltaV par Time.deltaTime et de diviser en masse, je dis juste que je veux ForceMode.Force et c'est géré de manière correcte et cohérente. Et lorsque moi ou quelqu'un d'autre vient itérer sur mon code plus tard, c'est immédiatement clair ce que je voulais dire, sans avoir besoin de décoder les calculs de temps et de masse pour le comprendre.

DMGregory
la source
6

En plus de la réponse de Trojanfoe , Angry Birds vs Car Racing. Deux exemples majeurs et différents de ces méthodes ( AddForceet velocityrespectivement). Par exemple, dans Angry Birds, l'utilisation de la vitesse est un peu plus difficile car vous devez définir la trajectoire du projectile par vous-même, comme,

Lorsque j'utilise AddForce dans Angry Birds, j'utilise,

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

Alors que lorsque j'utilise la vitesse, je gérerais la trajectoire en utilisant

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

Ou quelque chose comme ça.

Dans le jeu de course automobile, vous devez contrôler la vitesse tout le temps, pas comme Angry Birds, c'est-à-dire tirer et tout. Donc, dans ce scénario, le handle velocityest plus utile que AddForce.

J'espère que tu as compris. Au moins un peu.

Hamza Hasan
la source
1
Votre exemple AngryBirds devrait probablement utiliser un changement instantané de l'élan (par exemple, Impulse ou VelocityChange) lorsque la fronde est libérée, plutôt que le ForceMode.Force par défaut qui simule son effet sur une fenêtre de temps. Vous pouvez régler les nombres pour obtenir un comportement équivalent dans l'une ou l'autre approche, mais si vous modifiez votre pas de temps fixe, la solution de force aura une sortie différente (car elle intègre la force sur un intervalle de temps plus ou moins long) tandis que l'impulsion reste cohérente comme souhaité, car il représente juste le moment de la sortie.
DMGregory
0

Rigidbody Velocity et Rigidbody Addforce sont deux fonctions déroutantes dans Unity 3D et souvent les débutants ne comprennent pas leur différence. Dans cet article, nous allons discuter de la différence entre RigidBody.velocity et RigidBody.addforce.

Dans les deux cas, que ce soit la fonction Addforce ou la fonction de vitesse, nous allons utiliser le terme force pour les expliquer.

Lorsque nous utilisons Rigidbody.velocity, alors, dans ce cas, nous ajoutons de la force à notre objet, mais cette force ne fera que déplacer l'objet à moins et jusqu'à ce que nous continuions à appliquer la force.

Par exemple

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

Disons que vous avez ajouté 5f en position z et que la force sera ajoutée lorsque vous appuyez sur la touche W. Ainsi, lorsque vous appuyez sur la touche W, l'objet démarre instantanément à la vitesse de 5. C'est la même chose si vous ajoutez de la force en utilisant cette fonction sur une voiture, cette voiture démarrera à la vitesse de 5.

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

Et si vous permettez de modifier la valeur à 200, puis après l'enregistrement, appuyez sur W. La voiture commencera à fonctionner à la vitesse de 200 du démarrage, ce qui n'est pas possible dans le monde réel.

Maintenant, si vous parlez de Rigidbody.addforce

En continuant notre exemple de voiture. si vous ajoutez la force de 200 à la voiture

body.addforce (0,0,200);

La voiture ne commencera pas à se déplacer à la vitesse de 200 si nous appuyons sur W, mais elle démarre à partir de la vitesse lente, puis augmente sa vitesse et s'arrête en fonction de la valeur de la traînée.

Rigidbody.addforce démarre lentement puis accélère, tout comme vous faites glisser une table lourde, vous commencerez d'abord à pousser cette table, la table se déplacera juste un peu de sa position, mais si vous continuez à pousser cette table, elle commencera à bouger & si vous quittez cette table, elle couvrira une certaine distance en fonction de la surface et c'est la même chose que le corps rigide.

Vous pouvez utiliser Rigidbody.velocity où vous voulez simplement déplacer votre objet pour réagir instantanément comme le saut du joueur et le résultat de cette force disparaîtra juste après le saut et vous pouvez utiliser Rigidbody.addforce là où vous avez besoin d'un démarrage lent puis du mouvement continu comme une fusée. Si vous utilisez Rigidbody.addforce en saut, le joueur / objet restera dans l'espace pendant un certain temps puis reviendra au sol.

(la source)

Numan Hamza
la source
Vous devriez au moins essayer d'adapter votre message au format d'une réponse Stack Exchange :)
Vaillancourt