Unity - Come spostare realisticamente una nave in un punto in un gioco top-down 2D


14

sto cercando di spostare una nave a vela nel punto in cui ho cliccato con il mouse. questo movimento dovrebbe essere realistico (remi sul retro dove si muove la nave), quindi se il clic del mouse viene lasciato e davanti alla nave la nave dovrebbe successivamente spostarsi lì con un percorso sinuoso per avere la giusta rotazione

sarei felice se qualcuno potesse aiutarmi con questo problema grazie movimento della nave


1
Dato che la tua immagine sembra raffigurare le vele: il vento dovrebbe essere preso in considerazione? Alcune manovre sono impossibili da fare con il vento sbagliato o la loro mancanza.
Nessuno l'

Più precisamente, il movimento realistico di una nave a vela richiede davvero di prendere in considerazione il vento; ignorarlo sarebbe quasi come ignorare la gravità quando si implementa il salto. Non hai necessariamente bisogno di un modello di vento particolarmente dettagliato, ma devi tenere presente che le tue navi vengono spinte in giro dal vento nelle loro vele (e dall'acqua contro la loro chiglia e il timone). In particolare, le navi non possono navigare direttamente sopravento; avranno bisogno di battere la loro strada lì, invece.
Ilmari Karonen,

Solitamente un "goto point" può essere suddiviso in fase di rotazione e fase di movimento in avanti. Prendi lo stesso approccio ma imponi alla rotazione un movimento in avanti. Esempio ogni x rad di rotazione sposta la barca in avanti di y metri
dnk drone.vs.drones

Risposte:


7

Vedi questa pagina

Aggiunta di svolte realistiche

Il prossimo passo è aggiungere curve curve realistiche per le nostre unità, in modo che non sembrino cambiare bruscamente direzione ogni volta che devono girare. Una soluzione semplice prevede l'uso di una spline per smussare gli angoli bruschi in curve. Mentre questo risolve alcune delle preoccupazioni estetiche, si traduce ancora in un movimento fisicamente molto irrealistico per la maggior parte delle unità. Ad esempio, potrebbe cambiare una curva improvvisa di un carro armato in una curva stretta, ma la curva curva sarebbe ancora molto più stretta di quanto il carro armato potrebbe effettivamente eseguire.

Per una soluzione migliore, la prima cosa che dobbiamo sapere è il raggio di sterzata per la nostra unità. Il raggio di sterzata è un concetto abbastanza semplice: se sei in un grande parcheggio nella tua auto, e gira la ruota a sinistra fino in fondo e procedi a guidare in un cerchio, il raggio di quel cerchio è la tua svolta raggio. Il raggio di sterzata di un Maggiolino Volkswagen sarà sostanzialmente più piccolo di quello di un SUV di grandi dimensioni, e il raggio di sterzata di una persona sarà sostanzialmente inferiore a quello di un grande orso che si muove lentamente.

Diciamo che sei ad un certo punto (origine) e puntato in una certa direzione, e devi arrivare ad un altro punto (destinazione), come illustrato nella Figura 5. Il percorso più breve si trova girando a sinistra fino a te puoi, andando in un cerchio fino a quando non sei puntato direttamente verso la destinazione, e quindi procedendo in avanti, oppure girando a destra e facendo la stessa cosa. Figura 5: Determinazione del percorso più breve dall'origine alla destinazione.

Nella Figura 5 il percorso più breve è chiaramente la linea verde in basso. Questo percorso risulta essere abbastanza semplice da calcolare a causa di alcune relazioni geometriche, illustrate nella Figura 6.

Figura 6: calcolo della lunghezza del percorso.

In primo luogo calcoliamo la posizione del punto P, che è il centro del nostro cerchio di svolta, ed è sempre il raggio r lontano dal punto iniziale. Se stiamo girando a destra dalla nostra direzione iniziale, significa che P è ad un angolo di (initial_direction - 90) dall'origine, quindi:

angleToP = initial_direction - 90
P.x = Origin.x + r * cos(angleToP)
P.y = Origin.y + r * sin(angleToP)

Ora che conosciamo la posizione del punto centrale P, possiamo calcolare la distanza da P alla destinazione, mostrata come h sul diagramma:

dx = Destination.x - P.x
dy = Destination.y - P.y
h = sqrt(dx*dx + dy*dy)

A questo punto vogliamo anche verificare che la destinazione non sia all'interno del cerchio, perché se fosse, non potremmo mai raggiungerla:

if (h < r)
    return false

Ora possiamo calcolare la lunghezza del segmento d, poiché conosciamo già le lunghezze degli altri due lati del triangolo rettangolo, ovvero h e r. Possiamo anche determinare l'angolo dalla relazione del triangolo rettangolo:

d = sqrt(h*h - r*r)
theta = arccos(r / h)

Infine, per capire il punto Q in corrispondenza del quale lasciare il cerchio e iniziare sulla retta, abbiamo bisogno di conoscere l'angolo totale +, ed è facilmente determinato come l'angolo da P alla destinazione:

phi = arctan(dy / dx) [offset to the correct quadrant]
Q.x = P.x + r * cos(phi + theta)
Q.y = P.y + r * sin(phi + theta)

I calcoli sopra riportati rappresentano il percorso con svolta a destra. Il percorso a sinistra può essere calcolato esattamente allo stesso modo, tranne per il fatto che aggiungiamo 90 a initial_direction per il calcolo di angleToP, e successivamente usiamo - invece di +. Dopo aver calcolato entrambi, vediamo semplicemente quale percorso è più breve e usiamo quello.

Nella nostra implementazione di questo algoritmo e di quelli che seguono, utilizziamo una struttura di dati che memorizza fino a quattro distinti "segmenti di linea", ognuno dei quali è dritto o curvo. Per i percorsi curvi qui descritti, vengono utilizzati solo due segmenti: un arco seguito da una linea retta. La struttura dei dati contiene membri che specificano se il segmento è un arco o una linea retta, la lunghezza del segmento e la sua posizione iniziale. Se il segmento è una linea retta, la struttura dei dati specifica anche l'angolo; per gli archi, specifica il centro del cerchio, l'angolo iniziale sul cerchio e i radianti totali coperti dall'arco.

Una volta calcolato il percorso curvo necessario per raggiungere due punti, possiamo facilmente calcolare la nostra posizione e direzione in un dato istante nel tempo, come mostrato nel Listato 2.

ELENCO 2. Calcolo della posizione e dell'orientamento in un determinato momento.

distance = unit_speed * elapsed_time
loop i = 0 to 3:
    if (distance < LineSegment[i].length)
        // Unit is somewhere on this line segment
        if LineSegment[i] is an arc
            //determine current angle on arc (theta) by adding or
            //subtracting (distance / r) to the starting angle
            //depending on whether turning to the left or right
            position.x = LineSegment[i].center.x + r*cos(theta)
            position.y = LineSegment[i].center.y + r*sin(theta)
        //determine current direction (direction) by adding or
        //subtracting 90 to theta, depending on left/right
        else
            position.x = LineSegment[i].start.x 
              + distance * cos(LineSegment[i].line_angle)
            position.y = LineSegment[i].start.y
              + distance * sin(LineSegment[i].line_angle)
        direction = theta
        break out of loop
    else
        distance = distance - LineSegment[i].length

4
Questa risposta non esamina davvero la fisica delle navi. Trovo inoltre problematico che si tratti sostanzialmente di un collegamento e di un lungo estratto da un altro sito Web (non sono sicuro della legalità).
Nessuno l'

L'ultima volta che ho fornito una risorsa esistente che era una soluzione alla domanda che mi veniva posta, mi è stato chiesto di includere il contenuto del link nel caso in cui il sito di destinazione cessasse di essere. Ora mi viene chiesto di non includere il contenuto. Decidi.
Draco18s non si fida più di SE

3
@ Draco18s: Quello che dovresti fare è riassumere in parole tue i punti essenziali del materiale collegato. (O, meglio ancora, rispondi alla domanda in base alla tua esperienza personale e usa i link solo come materiale di supporto o per ulteriori letture.) Le virgolette brevi sono generalmente OK, soprattutto in situazioni in cui non possono essere realmente evitate (ad esempio, citare l'esatto di qualcuno parole per dimostrare che hanno davvero detto qualcosa), ma citare una parte sostanziale di un articolo va davvero oltre il fair use .
Ilmari Karonen,

Se il punto si trova all'interno del cerchio, puoi uscire un po 'e tornare indietro.
user253751

(Sal. Vedi anche queste due domande su meta.SE.)
Ilmari Karonen l'

7

Come soluzione semplice, come ho già detto in un commento, puoi provare questo approccio:

considerare una fase in cui si punta la nave nella direzione target, in quella fase si applica una rotazione al sorso ma anche un movimento in avanti. Quando la nave è già di fronte al bersaglio, puoi applicare una velocità di avanzamento completa. Ho organizzato un test in love2d, qui segui il metodo di aggiornamento della nave.

turnAngSpeed = 0.4 --direction changing speed
ForwordSpeed = 40 -- full forward speed
turnForwordSpeed = ForwordSpeed *0.6 -- forward speed while turning
function ent:update(dt)
            dir = getVec2(self.tx-self.x,self.ty-self.y) -- ship --> target direction (vec2)
            dir = dir.normalize(dir) --normalized                               
            a= dir:angle() - self.forward:angle() --angle between target direction e current forward ship vector
            if (a<0) then
             a=a+math.pi *2 -- some workaround to have all positive values
            end

            if a > 0.05 then -- if angle difference 
                if a < math.pi then
                    --turn right
                    self.forward = vec2.rotate(self.forward,getVec2(0,0),turnAngSpeed * dt)
                else
                    --turn left
                    self.forward = vec2.rotate(self.forward,getVec2(0,0),-turnAngSpeed * dt)
                end             
                --apply turnForwordSpeed
                self.x = self.x+ self.forward.x * turnForwordSpeed * dt
                self.y = self.y+ self.forward.y * turnForwordSpeed * dt
            else 
                --applly ForwordSpeed
                self.x = self.x+ self.forward.x * ForwordSpeed * dt
                self.y = self.y+ self.forward.y * ForwordSpeed * dt
            end
end

inserisci qui la descrizione dell'immagine

L'animazione di esempio mostra (il ciclo finale) un caso in cui la nave non può raggiungere il bersaglio, poiché la combinazione di velocità di virata e di avanzamento definisce un raggio di virata troppo grande, in questo caso può essere utile ridurre " turnForwordSpeed" o renderlo migliore dipende dalla distanza angolare ( a) e dalla distanza target.


Questa è una bella risposta, ma può essere o non essere abbastanza realistica per il PO. A differenza, diciamo, delle automobili, le navi non hanno davvero un "raggio di sterzata": la maggior parte delle navi a motore autonomo (motore / umano) può essenzialmente accendere un centesimo, mentre le navi a vela dipendono dal vento e possono effettivamente avere una svolta efficace negativa raggio di virata, nel senso che la svolta a sinistra nel vento può causare la deriva della nave a destra. Ciò che hanno le navi è l'inerzia (e il trascinamento): non possono girare o muoversi all'istante, e una volta che si muovono o girano, impiegano un po 'di tempo e forza per fermarsi. Tuttavia, hai un +1.
Ilmari Karonen,

Grazie mille per la tua risposta!!! :) signore sei il mio eroe!
David

@DavidT Quindi considera di contrassegnare la sua risposta come accettata, se è stata in grado di risolvere il tuo problema in modo soddisfacente. :)
MA il

-2

Sistema mesh Unity Nav, probabilmente farebbe quello che vuoi con un po 'di gioco con i valori dell'agente nav.

Le Mesh Nav sono piuttosto semplici da usare. E utilizzabile solo nella configurazione top down (o almeno disponibile solo per il movimento x / z)

Pagina manuale Unity su come impostare una mesh nav

Fondamentalmente puoi usare qualsiasi mesh di forma per creare un'area di navigazione e aggiungere agenti di navigazione ai tuoi oggetti e far loro trovare i loro percorsi attorno a una mesh di navigazione


Trovo che la risposta di Draco18s manchi anche in questo senso. Tuttavia, la tua non è una vera risposta e più di un commento.
Nessuno l'

2
Questo è un buon suggerimento ma, per essere una buona risposta, necessita di supporto e informazioni sull'attuazione. Si prega di aggiungere alcune informazioni sulla configurazione di mesh nav per rendere questa una buona risposta. Penso che sia quello che i commentatori sopra stanno cercando di dire :)
sirdank
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.