Pocisk kierowany ze stałym czasem

9

Buduję grę z graczami i pociskami.

Chcę wystrzelić pocisk z P1 do P2. Dotarcie do P2 zawsze powinno zająć dokładnie pięć sekund. Pocisk powinien również śledzić P2. Jeśli P2 odsunie się dalej, pocisk musi przyspieszyć, aby spełnić ograniczenie czasowe. Jeśli P2 przesunie się w lewo, pocisk musi przesunąć się w lewo (i również zmienić prędkość). Jeśli P2 zbliży się do P1, pocisk musi zwolnić.

czy to możliwe? Jaki jest najlepszy sposób na osiągnięcie tego?

Obecnie nie mam klasy Vector2D (to właściwie nie jest gra, ale analogia działa dobrze), więc jeśli to możliwe, chciałbym rozwiązania, które nie wymaga takiej.

Edycja: To właściwie nie jest pocisk. :)

Dzięki!

Piotr
źródło
1
(Trochę boję się, że ktoś zapyta o prowadzenie pocisku kwalifikowanego przez „to nie jest właściwie gra”, ale…) Czy masz jakieś ograniczenia co do kształtu trajektorii pocisku? Czy zawsze może podążać linią prostą między obecną pozycją a graczem 2? Czy ma jakiś limit promienia skrętu lub przyspieszenia? Czy trzeba unikać przeszkód? Wspominasz także Vector2D - czy można bezpiecznie założyć, że potrzebujesz go tylko w 2D? Możesz wykonać całą matematykę wektorową komponentowo, ale pisanie jest nieporęczne w porównaniu z prostą klasą matematyki wektorowej, więc tak naprawdę nie rozumiem preferencji.
DMGregory
Przegapiłeś dodatkowe informacje. Czy są ograniczenia? Czy pociski poruszają się wzdłuż linii, czy też powinniśmy dbać o kierunki i ile ostatecznie wymiarów?
liggiorgio 16.04.16
Ścieżka nie powinna być ograniczona. Jedyne zasady to: A) „Pocisk” powinien zawsze podejmować kroki w kierunku celu. B) „Pocisk” powinien zawsze dotrzeć na 5 sekund. Pisanie klasy Vector2D nie stanowi problemu. Po prostu nie mam jednego przydatnego (a matematyka nie jest moim najlepszym przedmiotem). Jeśli to ułatwi, mogę to dodać.
Peter
Najprostszym sposobem na to jest użycie splajnu pustelniczego i obliczenie wartości parametrycznej.
Steven Srun,

Odpowiedzi:

11

Edycja jest uspokajająca. :)

Dobra, oto prosta pętla aktualizacji ...

Zakładając, że kiedy wystrzelimy pocisk, zainicjujemy remainingFlightTime = 5fwtedy ...

void UpdateMissile(float deltaTime)
{
   remainingFlightTime -= deltaTime;

   // At the end of the trajectory, snap to target & explode.
   // The math will put us there anyway, but this saves
   // on fancy logic related to overshooting. ;)
   if(remainingFlightTime <= 0f)
   {
      myX = targetX;
      myY = targetY;
      MissileImpact();
      return;
   }

   // Compute straight-line velocity that will take us
   // to the target in exactly the time remaining.
   velocityX = (targetX - myX)/remainingFlightTime;
   velocityY = (targetY - myY)/remainingFlightTime;

   // Integrate the velocity into the position.
   myX += velocityX * deltaTime;
   myY += velocityY * deltaTime;
}
DMGregory
źródło
1
Ta metoda nie sprawia, że ​​„pocisk” wydaje się obracać wokół swojego punktu startu w połowie lotu. +1
Jon
0

Dlaczego nie obliczyć pozycji i zaktualizować docelowego miejsca docelowego, gdy się zmienia?

Być może będziesz musiał spojrzeć na to, jak działa Lerping, ale wyglądałoby to mniej więcej tak:

public position startMarker;
public float duration = 5.0f;
private float startTime;
void Launch() {
    startTime = Time.time;
}
void Update() {
    float distCovered = (Time.time - startTime) / duration;
    missile.position = Vector3.Lerp(startMarker.position, target.position, distCovered);
}

przez przeciąganie zasadniczo zmieniasz pozycję obiektu w określonym czasie, abyś mógł powiedzieć, że jesteś w 50% drogi od A do B i obiekt zostałby tam umieszczony. Lerping jest bezpośredni, więc zawsze będziesz zbliżał się do celu (jak chcesz w komentarzach).

użytkownik3797758
źródło
no cóż, mój zły ... Chyba tak się stanie, jeśli spróbujesz napisać kod o 3 nad ranem. zmieniłem odpowiedź, aby naprawić błąd
użytkownik3797758