2011-09-09 10 views
8

In unità, ho una racchetta che dovrebbe colpire una palla e la racchetta è controllata direttamente dal mouse, cioè il pipistrello viene spostato da il mouse usando gli assi del mouse e la funzione transform.translate() per spostare la racchetta.Problema con il rilevamento di collisione di una palla che si muove rapidamente con una racchetta controllata con il mouse

Mi aspettavo che la fisica di Unity3d non traduca correttamente i movimenti della racchetta direttamente con il mouse e abbia un impatto sulla palla di conseguenza, e dovrei scrivere qualcosa di personalizzato, e si è rivelato essere vero.

Ma la collisione della palla non viene rilevata correttamente quando la racchetta si sta muovendo. Quando è fermo, tutto va bene e la palla si comporta come mi piace.

Ora sono arrivato a scrivere uno script di fisica personalizzato (io uso C# per gli script) in cui ho collegato 4 raycast di lunghezza 0.6F alla pallina, e dopo aver fatto alcuni calcoli vettoriali complessi, calcolare la velocità della palla dopo aver colpito la racchetta, e applicarlo direttamente alla velocità della palla usando rigidbody.velocity = calculateVelocity(). Ora funziona di nuovo bene quando la racchetta non si muove, ma non quando muovo la racchetta. Il problema esatto (sintomi del) è:

Uso della rilevazione fisica e della collisione incorporata: quando la racchetta si muove, la palla passa a volte attraverso la racchetta e, a volte, rallenta (a livelli incredibili).

Utilizzo del mio script per calcolare la velocità: il problema è lo stesso, ma mi consente di identificare ciò che è sbagliato quando stampo il normale del collisore (la racchetta). A volte dà il diritto normale, e qualche volta dà il negativo del vettore normale, il che significa che sta andando dritto attraverso la superficie superiore e rilevando il colpo con il lato inferiore del collisore (racchetta).

Le cose che ho provato:

  1. L'aumento delle dimensioni del collider (funziona con la casella collider più ampio sulla racchetta, ma poi, ovviamente, la palla si muove da una certa distanza dal racket, e il mio script funziona qui, la fisica di default dà strani risultati quando si muove la racchetta), in breve non capisco la realtà che voglio.

  2. Diminuendo il timestamp fisso a 0,001, che ha migliorato in modo significativo le cose, ma ancora molto molto lontano dal risultato che voglio, e la palla è ancora abbastanza spesso raccogliendo il lato sbagliato della palla.

  3. Modifica del rilevamento di collisione su dinamica continua. Neanche questo ha migliorato le cose.

Ed oltre al lato sbagliato scelto a collisione, un altro problema che ho osservato è che dopo rimbalzando la racchetta, la palla è muove ma la racchetta viene spostato più veloce, invece di muoversi in un arco completo o linea, in qualche modo appare davanti alla palla, risultando in due colpi. È una congettura basata su ciò che è visibile.

Inoltre è chiaro che l'aspetto "movimento" della racchetta non viene letto dalla fisica incorporata di Unity3d, risultando in uno strano comportamento quando la racchetta si muove usando il mouse per colpire la palla.

Sono bloccato, non ho idea di dove spostare da qui. Per favore dimmi cosa sto facendo di sbagliato.

risposta

8

Come altri hanno sottolineato, il problema è che la palla passa dall'essere su un lato del pad in un frame per essere dall'altro lato nel successivo. Gli oggetti in rapido movimento tendono a farlo se le barriere sono troppo sottili.

ci sono tre soluzioni molto semplici per questo problema:

  • aumentare le dimensioni del pad o la palla, che è quello che è successo quando è stata modificata la dimensione del collisore.
  • Stabilire una velocità massima per la palla, in modo che non possa mai muoversi abbastanza velocemente da passare attraverso i pad.
  • Aumentare la frequenza con cui Unity esegue i calcoli fisici. Può essere modificato in Time Manager, riducendo il valore di Fixed Timestep. Attenzione a ridurre troppo questo, o il motore fisico non sarà in grado di terminare una chiamata prima che il prossimo round dovrebbe iniziare e non sarà mai in grado di raggiungere il gioco.

L'impostazione di una velocità massima per lo spostamento di oggetti è qualcosa che deve sempre essere fatto. Non puoi rischiare di avere un oggetto importante che salta alle stelle durante il gioco e lasciare tutto in uno stato incontrollato.

+0

Ho provato a impostare la massima velocità sia per la racchetta che per la palla, posso forse aumentare le dimensioni dell'intero ambiente, forse questo potrebbe dare maggiori possibilità di rilevare il lato destro del collisore. Implementerò sia la soluzione fornita da Justin808 che aumenterò le dimensioni di tutto. – SpeedBirdNine

+0

Questa cosa ha funzionato così bene, ho raddoppiato le dimensioni di tutto, e ora non manca una collisione. Ho ancora l'altro problema di cui parlava Justin808, che la racchetta in un momento è davanti alla palla e il fotogramma successivo è dietro la palla, ma almeno vedo due collisioni distinte, che possono essere gestite con il codice! Molte grazie! Mi ci sono voluti solo 2 minuti per farlo. Ora ho intenzione di implementare la soluzione di Justin per risolvere due collisioni. A questo punto se qualcuno ha altre spiegazioni, per favore condividi anche tu! – SpeedBirdNine

+0

Risolto il problema, non ho dovuto posizionare un raggio tra la posizione precedente e quella successiva della palla, poiché ora il collisore della racchetta non manca la palla. L'altra cosa è che il movimento della racchetta attraverso il mouse non si traduce in un'ulteriore forza applicata alla palla. Ho dovuto scrivere questa parte da solo, e impostare istrigger come vero per il collisore della racchetta in modo che la fisica originale non interferisca. Ma ora c'era il problema di colpire più volte, l'ho risolto usando un flag, che diventa falso quando viene colpito per la prima volta, e true di nuovo dopo 1 secondo, o quando la palla colpisce un altro oggetto. Funziona! – SpeedBirdNine

3

Questa non è una risposta completa, ma ricordo di aver avuto a che fare con un problema come questo molti anni fa su macchine più lente.

Il problema riguardava il rilevamento delle collisioni basato su sprite; basandosi sui pixel per lo sprite e l'ostacolo che viene reso alle stesse coordinate. Se la frequenza dei fotogrammi è così bassa che lo sprite si muove più della dimensione dell'ostacolo in un fotogramma, ti troverai in situazioni in cui è (ad esempio) a sinistra dell'ostacolo in un fotogramma e a destra dell'ostacolo nel fotogramma successivo senza mai occupando gli stessi pixel.

In questo caso le collisioni basate su sprite non funzionano, è necessario basare le collisioni sui vettori. Invece di controllare ogni pixel di sprite per le collisioni, registra la posizione e convesso lo scafo dello sprite. Dopo ogni fotogramma, calcola un vettore dalla vecchia posizione alla nuova posizione e intersecarlo con lo scafo convesso di ogni ostacolo.

Esistono più scorciatoie da eseguire, come il confronto solo con i riquadri di delimitazione e il calcolo dello scafo solo se il vettore interseca un riquadro di delimitazione, ma questa è l'idea di base. In bocca al lupo.

+1

L'idea sembra un buon punto di partenza, ma qualsiasi idea su come implementarla in Unity3d usando il maggior numero possibile di cose integrate (a questo è ottimizzata). E su macchine lente, l'ho testato su una macchina core i7 con 6 GB di RAM DDR3 e 1 GB di scheda grafica ATi Radeon HD5890, e FPS non scende mai sotto i 70. E per favore spiegate cosa sono i rilevamenti di collisioni basati su sprite ed è ciò che Unity3d usa ? Dal momento che sto usando Unity3d, non credo che sarò in grado di controllare le specifiche del meccanismo di rilevamento delle collisioni in questa misura – SpeedBirdNine

+1

Spiacente, non ho usato Unity. La grafica basata su sprite utilizza il frame buffer effettivo per i calcoli; se stai usando OpenGL o ActiveX probabilmente non stai usando sprite. Tuttavia, la nozione di controllare i vettori contro gli scafi convessi per le collisioni è applicabile alla grafica in modalità conservata. Immagino che Unity abbia un modo di vedere se un vettore interseca uno scafo. –

+0

Qualche altra risposta a qualcuno? – SpeedBirdNine

5

Quello che penso stia accadendo è che ogni intervallo che accade la palla/racchetta viene spostato e quindi controllato per una collisione. Il problema è che la palla/racchetta si muove verso il lontano in un singolo intervallo e salta la collisione.

1) Ball before racquet 
2) Ball after racquet 

not 

1) Ball before racquet 
2) Ball touching racquet 

Quindi quello che dovete fare è nel metodo di vostra FixedUpdate() del vostro GameObject palla è gettata un raggio dalla posizione palla corrente alla posizione sfera precedente. Se c'è qualcosa tra quei due punti che dovrebbero essere stati colpiti (cioè la racchetta), sposta la pallina indietro al punto colpito del raggio. Ciò attiverà il tuo materiale esistente per il rilevamento delle collisioni.

Il motivo per cui aumenta anche la dimensione del collisore è perché la palla non salta il collisore lager. Questo ha gli svantaggi che hai citato nella tua domanda. Il raggio di lancio evita questo problema e consente alla palla/racchetta di muoversi più velocemente o lentamente come è necessario.

0

Ho lavorato anche a un gioco pong 3D e ho incontrato gli stessi identici problemi. Ho intenzione di provare ad allargare tutto come hai fatto tu. Per quanto riguarda la pagaia che aggiunge velocità e rotazione alla palla, ne sono rimasto sconcertato fino a quando ho capito che cambiare la posizione della pagaia non cambia la sua velocità. Se la pagaia era a velocità zero prima di essere spostata, sarà a zero quando il motore fisico la guarderà al prossimo frame.Un controllo è kenimatico e il controllo della paletta direttamente attraverso la proprietà di velocità ha risolto il problema. Ciò ha causato il jitter della paletta quando si toccavano i muri, ma l'ho risolto rimuovendo le pareti dal livello delle palette e gestendo i limiti manualmente in LateUpdate. Inoltre, quando si aggiorna la velocità, è necessario innanzitutto memorizzare la nuova velocità desiderata in Aggiornamento in modo che i controlli funzionino correttamente, quindi confermare le modifiche in FixedUpdate.

Problemi correlati