Kiedy powinienem używać prędkości w porównaniu z addForce, gdy mamy do czynienia z obiektami gracza?


18

Mam wątpliwości co do tych dwóch metod w ramach Unity. Oba sprawiają, że obiekt gracza porusza się, zatrzymuje, zmienia kierunek itp. Kiedy należy użyć jednego nad drugim i kiedy jest odpowiedni?



@ Byte56 oba pytania dotyczą różnych rzeczy
Robert

1
Różne, ale powiązane. Właśnie dlatego są one połączone, a nie duplikaty. Pokaż to pokazuje w połączonej kolumnie po prawej stronie.
MichaelHouse

Odpowiedzi:


13

Używałbyś velocitydo poruszania obiektem ze stałą prędkością (na przykład pocisk) i AddForce()do dodawania ruchu (na przykład pędnika statku kosmicznego). Zauważ też, że istnieją dwa „rodzaje” ruchu; siła i impuls. Jako ster strumieniowy statku kosmicznego użyłbyś impulsu.


4
Czy możesz opisać, dlaczego wolisz impulsy dla pędnika kosmicznego? Może to nie być idealne dopasowanie, jeśli stosuje się stopniowe przyspieszenie w czasie, a nie natychmiastowe zmiany pędu spowodowane uderzeniami broni. Stosowane w oknie czasowym zazwyczaj potrzebujesz siły (lub przyspieszenia, jeśli nie chcesz, aby masa była czynnikiem), a jednocześnie natychmiast
użyłbyś

@DMGregory Tak, to zależy od rodzaju siły, którą chcesz dodać. W moim przykładzie steru statku kosmicznego, który jest chwilowym wybuchem energii, właściwym wyborem jest impuls.
trojanfoe,

2
Nie było od razu jasne, czy chodziło Ci o krótkie odpalenie odrzutowca nastawczego, czy o ciągłe spalanie silnika głównego (czasami „thruster” jest czasem używany nieco w science fiction), więc pomyślałem, że powinienem wyjaśnić, żeby ktoś nie spróbował za pomocą impulsów dla rakiety. ;)
DMGregory

@DMGregory Rzeczywiście; moja terminologia dotycząca technologii kosmicznej opiera się w dużej mierze na filmach :)
trojanfoe,

@trojanfoe Go zagraj w KSP. Jak teraz.
user253751,

21

Chociaż istnieje już akceptowana odpowiedź, myślę, że warto podać dodatkowe szczegóły.

Korzystanie z prędkości

Kiedy ustawiasz prędkość, nadpisujesz absolutnie wszystko, co może wpłynąć na ruch tego obiektu. W niektórych sytuacjach jest to pożądane, na przykład ustawienie początkowej prędkości pocisku w momencie jego wystrzelenia, jak w przykładzie trojanfoe. Bądź ostrożny, ponieważ użycie go w niewłaściwych sytuacjach może powodować problemy:

  • Jeśli wiele źródeł / skryptów próbuje zmodyfikować tę samą prędkość Sztywnego Ciała poprzez ustawienie jej bezpośrednio (tj. body.velocity = foo), To jedno z nich, które uruchomi ostatnie, wygrywa, a inne mają zerowy efekt. Może to prowadzić do kolejności błędów aktualizacji, w szczególności powodować powolne zawisanie lub opadanie bytów (ponieważ przyspieszenie w dół z powodu grawitacji zostaje nadpisane, zanim będzie mogło się akumulować)

  • Jeśli ustawiasz prędkość dla każdej klatki, kolizje z innymi obiektami mogą być nieco dziwne. To tak, jakby twój obiekt był napędzany silnikiem o nieskończonym momencie obrotowym - bez względu na to, jaką prędkość traci podczas uderzenia, wraca do maksymalnej prędkości na następnym etapie fizyki, a jego prędkość nie jest odchylana od uderzenia . Może to prowadzić do wystrzeliwania obiektów, z którymi się zderzasz, lub małych obiektów jest w stanie popychać duże o wiele łatwiej, niż wydaje się, że powinny, lub obiektów przesuwających się powoli wzdłuż barier statycznych zamiast odchylać się wzdłuż nich.

Oba te efekty mogą być czasem pożądane. Na przykład, gdy tworzę gry Kinect i chcę, aby kończyny wirtualnego awatara gracza mogły wchodzić w interakcje ze sceną fizyki, zwykle poruszam tymi ciałami przy użyciu bezpośredniego ustawienia prędkości. Ponieważ faktyczna ręka gracza jest w znanym miejscu i nie zwalniać od zderzenia z tego wirtualnego obiektu, ich wirtualne potrzeby ręcznie zrobić to samo, aby pozostać w zgodzie, a więc w tym przypadku rzeczywiście chcą , aby zastąpić wszystkie inne efekty fizyki dostać to tam.

AddForce and Friends

Z kolei AddForce i podobne funkcje pomocnicze są przystosowane do współpracy ze wszystkim, co dzieje się w świecie fizyki. Jeśli wiele źródeł / skryptów dodaje siłę do sztywnego ciała, wszystkie te efekty są sumowane, aby utworzyć netto zmianę w ruchu obiektu (który, w zależności od sposobu obliczenia, może również być niezależny od kolejności). Pomaga to uniknąć jednego skryptu całkowicie zagłuszającego inny efekt fizyczny.

AddForce występuje w czterech odmianach, określając opcjonalny parametr ForceMode , które są przydatne do różnych rzeczy:

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

Jeśli próbujesz modelować ciągłe wypychanie w czasie (np. Coś, co stosujesz przy każdej FixedUpdate), na przykład podczas jazdy samochodem lub spalania rakiety lub grawitacji, potrzebujesz siły lub przyspieszenia. (W zależności od tego, czy chcesz, aby ciężkie przedmioty przyspieszały wolniej)

Jeśli modelujesz nagłą, gwałtowną zmianę ruchu, taką jak wystrzelenie kuli, odskoczenie od eksplozji lub odbicie się od bariery, bardziej prawdopodobne jest, że chcesz zmienić Impuls lub Szybkość.

Korzystanie z AddForce pomaga osiągnąć większy realizm fizyczny, ale może również wymagać poświęcenia więcej czasu na przemyślenie fizyki swojego zachowania. Na przykład, jeśli chcesz, aby twoje ciało miało skończone przyspieszenie do prędkości docelowej, aby reagowało bardziej realistycznie na zderzenia niż ustawianie prędkości w każdej klatce, prawdopodobnie będziesz potrzebować obliczeń podobnych do tej funkcji pomocniczej:

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

Powodem, dla którego nazywam te wszystkie „funkcje pomocnicze” jest to, że technicznie można osiągnąć te same cele dzięki:

 body.velocity += suitablyCalculatedDeltaV;

( Wydaje mi się, że możliwe jest to, że bufor fizyki Unity oparty na PhysX / Box2D zmienia bufor osobno przez AddForce, ale nie widziałem oczywistych konsekwencji tego)

Tak więc na koniec dnia to, co naprawdę zyskują te funkcje, to jasność intencji . Kiedy chcę zastosować stopniową siłę, nie muszę pamiętać, aby pomnożyć moją deltaV przez Time.deltaTime i podzielić przez masę, po prostu mówię, że chcę ForceMode.Force i jest obsługiwany w prawidłowy i spójny sposób. A kiedy ja lub ktoś inny przyjdzie później do iteracji mojego kodu, od razu staje się jasne, co miałem na myśli, bez potrzeby dekodowania obliczeń czasu i masy, aby to rozgryźć.


6

Oprócz odpowiedzi trojanfoe , Angry Birds vs Car Racing. Dwa główne i różne przykłady tych metod ( AddForcei velocityodpowiednio). Na przykład w Angry Birds użycie prędkości jest trochę trudniejsze, ponieważ musiałbyś sam ustawić trajektorię pocisku, np.

Gdy używam AddForce w Angry Birds, używałbym,

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

Podczas gdy kiedy używam prędkości, radziłbym sobie z trajektorią

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

Lub coś w tym stylu.

Podczas gry w wyścigi samochodowe musisz cały czas kontrolować prędkość, a nie jak Angry Birds, czyli strzelać i wszystko. Więc w tym scenariuszu uchwyt velocityjest bardziej przydatny niż AddForce.

Nadzieję, że zrozumiesz. Przynajmniej trochę.


1
Twój przykład AngryBirds powinien raczej użyć chwilowej zmiany pędu (np. Impulse lub VelocityChange) po zwolnieniu procy, a nie domyślnej ForceMode.Force, która symuluje jego efekt w oknie czasowym. Możesz dostroić liczby, aby uzyskać równoważne zachowanie z dowolnego podejścia, ale jeśli zmienisz swój stały krok czasowy, rozwiązanie siły będzie miało inny wynik (ponieważ integruje siłę w dłuższym lub krótszym przedziale czasowym), podczas gdy impuls pozostaje spójny, ponieważ pożądane, ponieważ reprezentuje tylko moment wydania.
DMGregory

0

Rigidbody Velocity i Rigidbody Addforce to dwie mylące funkcje w Unity 3D i często początkujący nie rozumieją swojej różnicy. W tym artykule omówimy różnicę między RigidBody.velocity a RigidBody.addforce.

W obu przypadkach, niezależnie od tego, czy jest to funkcja Addforce, czy funkcja prędkości, użyjemy terminu siła, aby je wyjaśnić.

Kiedy używamy prędkości Sztywnego Ciała, wówczas w takim przypadku dodajemy siłę do naszego obiektu, ale siła ta porusza obiekt tylko, dopóki nie zastosujemy siły.

Na przykład

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

Powiedzmy, że dodałeś 5f w pozycji Z, a ta siła zostanie dodana po naciśnięciu klawisza W. Więc kiedy naciśniesz klawisz W, obiekt natychmiast rozpocznie się z prędkością 5. To tak samo, jeśli dodajesz siłę za pomocą tej funkcji w samochodzie, samochód zacznie się z prędkością 5.

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

A jeśli pozwolisz, powiedzmy, zmienić wartość na 200, a następnie po zapisaniu naciśnij W. Samochód zacznie biegać z prędkością 200 od uruchomienia, co nie jest możliwe w prawdziwym świecie.

Teraz, jeśli mówisz o Rigidbody.addforce

Kontynuując nasz przykład samochodu. jeśli dodasz siłę 200 do samochodu

body.addforce (0,0,200);

Samochód nie zacznie się poruszać z prędkością 200, jeśli naciśniemy W, ale zacznie od wolnego, a następnie zwiększy prędkość i zatrzyma się zgodnie z wartością Drag.

Rigidbody.addforce zaczyna się powoli, a następnie przyspiesza, tak jak przeciągasz ciężki stół, najpierw zaczniesz pchać ten stół, stół po prostu trochę się poruszy z jego pozycji, ale jeśli będziesz dalej pchał ten stół, zacznie się przesuwać i jeśli opuścisz ten stół, pokona on pewną odległość w zależności od powierzchni i to samo zrobi sztywne ciało. addforce.

Możesz użyć Rigidbody.velocity, gdzie po prostu chcesz przesunąć swój obiekt, aby zareagować natychmiast, jak skok gracza, a wynik tej siły zniknie tuż po skoku, a możesz użyć Rigidbody.addforce, gdzie potrzebujesz powolnego startu, a następnie ciągłego ruchu, takiego jak rakieta. Jeśli użyjesz Rigidbody.addforce w skoku, Gracz / Obiekt pozostanie przez pewien czas w kosmosie, a następnie wróci na ziemię.

(źródło)


Powinieneś przynajmniej spróbować dostosować swój post do formatu odpowiedzi Stack Exchange :)
Vaillancourt
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.