Fisica oscillante per il movimento del giocatore (come visto in Spider-Man 2 e Energy Hook)

Ciao! Sono Jamie Fristrom di Happion Laboratories. Potresti ricordarmi di giochi come Die By The Sword, Spider-Man 2 e Schizoid ... i quali, in una forma o nell'altra, includevano la corda. Ultimamente ho lavorato a un gioco chiamato Energy Hook - recentemente lanciato su Kickstarter - che riguarda la corda. (Beh, è ​​tutto sul tuo raggio di agglomerazione gravitonica, comunque.)


Parlerò di come mi piace implementare una meccanica di gameplay che oscilla la corda. Quando ho iniziato a lavorare su Energy Hook, ho fatto quasi tutto con il mio codice personalizzato. Credo che sia possibile andare semplicemente in Unity e usare il Joint Configurable per fare cose molto simili, ma al momento non era disponibile. Sono abbastanza sicuro che questa sia stata la chiamata giusta, comunque, perché mi dà il controllo su tutto - e posso condividerlo con te.


I fondamenti del fare oscillare come ho fatto io - usando vincoli - sono in realtà abbastanza semplici. (Spero tu non sia deluso quando vedi cosa c'è sotto il cofano.) Funziona allo stesso modo se stai facendo un gioco 2D o 3D, è solo che i vettori sono diversi, quindi inizierò con 2D e poi discuti alcune rughe quando vai a tre dimensioni.

Questo articolo presuppone anche che tu stia utilizzando un motore di gioco come Unity che può fare molto per te, come il raycasting contro la geometria e l'orientamento di un personaggio, con semplici chiamate di funzione. Se stai usando il tuo motore, potresti dover fare quel calcolo da solo.



Simulazioni fisiche vs. Movimento scatolato

Esistono due modi in cui le simulazioni di gioco spesso funzionano. La maggior parte dei giochi in terza persona ha conservato tutto; animazioni in scatola e movimenti inscatolati, quindi tutto sembra perfetto, i piedi del personaggio non scivolano, direttamente dal programma di animazione dell'animatore a noi. L'alternativa è una simulazione molto più fisica: stai simulando la fisica: accelerazione, velocità, gravità: molti giochi in prima persona lo fanno, ma i giochi in terza persona tendono ad evitarlo, perché è molto più facile avere i piedi del personaggio slide e le cose fisiche non corrispondono all'animazione.

Se vuoi fare uno swing di corda non in scatola (al contrario di uno swing di corda in scatola, come si vede nel primissimo Pitfall, oi primi giochi di Spider-Man come Neversoft's su PSX), uno swing di corda che è in realtà un fisico la simulazione e quindi può avere forse libertà e sfumature e la sensazione viscerale che la vera gravità e la quantità di moto possono darti, quindi vorrai farlo nel secondo modo - avere tutto come simulazione fisica ed evitare di fare cose in scatola che uccidono lo slancio del personaggio. Quindi, tutto scorre.

Questo è il modo in cui faccio cose con Energy Hook.


Ci sono un sacco di articoli là fuori su come simulare la fisica - eccone uno con una fantastica demo Flash integrata. Puoi fare l'integrazione di Euler o l'integrazione di Verlet, non ha molta importanza. (Non ti insegnerò qui su Eulero e Verlet, ma lasciami solo dire che i concetti non sono così spaventosi come sembrano).

Supponiamo di fare l'osso semplice integrazione di Eulero. Il tempo di gioco del nostro personaggio potrebbe assomigliare a questo, dove l'accelerazione è determinata dalla gravità e da come stai spingendo sul bastone:

 avatar.velocity = avatar.velocity + avatar.acceleration * deltaT; avatar.position = avatar.position + avatar.velocity * deltaT;

(Nota a margine: questa è in realtà un'approssimazione approssimativa: è possibile ottenere un'approssimazione migliore, meno framerate con avatar.position = avatar.position + (avatar.oldvelocity + avatar.velocity) * deltaT / 2.0f, e puoi ottenere una simulazione quasi perfetta con qualcosa del genere - ma i tuoi giocatori probabilmente non se ne accorgeranno.)

Post correlati
  • Simula Cloth e Ragdoll indossabili con una semplice integrazione Verlet
  • Come creare un motore di fisica 2D personalizzato

Constrain It

Probabilmente il tuo gioco ha un sistema per scontrarsi con la geometria del mondo. Probabilmente sembra qualcosa del genere:

 Vector testPosition = avatar.position + avatar.velocity * deltaT; Intersezione vettoriale se (RayCast (position, testPosition, out intersezione)) // abbiamo attraversato un muro, torniamo indietro, // usando il normale del muro // con uno spazio di 1 unità per il respirare testPosition = intersezione + intersezione.normale; 

Cosa succede alla velocità del tuo avatar quando colpisce un ostacolo? Non ha senso che il tuo avatar continui a mantenere la stessa velocità attraverso il muro. Alcuni giochi potrebbero rimbalzare, usando la normale di dove sei intersecato per riflettere la tua velocità; altri giochi potrebbero farti scivolare lungo il muro; altri saranno nel mezzo. Diamo un'occhiata al codice per lo scorrimento lungo un muro:

 avatar.velocity = (testPosition - avatar.position) / deltaT; avatar.position = testPosition;

(Se stai facendo l'integrazione Verlet, in cui ogni fotogramma stai già determinando la velocità semplicemente guardando i dati di posizione precedenti, questo passaggio è già fatto per te.)

Inoltre, i videogiochi sono le cose hacky che sono, probabilmente troverai spesso che la posizione del tuo personaggio scatta improvvisamente da un fotogramma all'altro in certi casi d'angolo. Quando ciò accade, la loro velocità passerà attraverso il tetto. La mia soluzione per questo è semplicemente un hack: controlla se la loro velocità diventa troppo estrema e risolvila se lo fa.

Che cosa fa quel codice quando colpisci un muro con un angolo? Il primo fotogramma, cambia drasticamente la tua velocità quando colpisci il muro, ma ti spinge ancora oltre il muro. Il fotogramma successivo, il tuo avatar viene aggiornato di nuovo nel muro, e poi spinto di nuovo fuori, ma ora la velocità è la nuova posizione dell'avatar, scivolata lungo il muro, meno la sua vecchia posizione, contro il muro, quindi è parallela al muro.

Questa è un'enorme semplificazione eccessiva di ciò che accade nel mondo reale quando un oggetto si scontra con un altro, ma la maggior parte dei tuoi giocatori non si accorgerà o non si preoccuperà.

A questo punto, però, abbiamo vincolato con successo la posizione e la velocità del nostro avatar con le pareti e i pavimenti del nostro gioco. Quindi ora siamo pronti.

Vincolare con gli attacchi invece dei muri

Quindi ora immagina che il tuo avatar sia già collegato da una corda virtuale a un punto virtuale. Per quanto ci riguarda, possiamo semplicemente considerare che un muro circolare o sferico invisibile. Possiamo testare la collisione vedendo se vi siete allontanati troppo dal centro del cerchio e riavvitate l'avatar.

 if (amITethered) if (testPosition - tetherPoint) .Length ()> tetherLength) // siamo oltre la fine della nostra corda // rientra l'avatar. testPosition = (testPosition - tetherPoint) .Normalized () * tetherLength; 

Ora, la stessa regolazione della velocità che ci ha fatto scivolare lungo i muri ci farà anche scivolare lungo l'interno di questo cerchio o sfera virtuale.


Fisica oscillante: caduta con un Tether - Frame 1
Fisica oscillante: caduta con un Tether - Frame 2
Fisica oscillante: caduta con un Tether - Frame 3

Qualche sottigliezza e sfumature

A questo punto, hai un gioco altalenante. Ma probabilmente ci saranno alcune cose che possono intralciare il divertimento dei tuoi giocatori, ed è qui che un piccolo hacking può migliorare le cose.

Slack, Springiness

A seconda del gioco e se si suppone che stia simulando una lunghezza di corda o una ragnatela elastica o un raggio di presa, si possono avere approcci diversi al rallentamento e al rigonfiamento. Puoi simulare un sacco di cose modificando il tetherLength. Se vuoi liberarti dalla rete elastica o dal raggio di presa, puoi accorciarlo tetherLength quando il giocatore si avvicina al punto di tethering:

 tetherLength = (avatar.position - tetherPoint) .Length ();

Ma se è una corda non elastica, lasceresti il tetherLength intatto.

Per elasticità, puoi avere un desiredLength questo è fisso e a currentLength che cerca continuamente di avvicinarsi al desiredLength - questo sarà anche utile per il nostro prossimo passo:

Ma non voglio colpire il terreno!

Cosa succede se il tuo avatar inizia in una posizione bassa e tenta di oscillare? È abbastanza ovvio che non andranno molto lontano. Una soluzione rapida per questo è controllare quanto in alto dal suolo il punto da cui vogliono oscillare, e accorciare la lunghezza del loro attacco in modo che possano liberare il terreno.

Non puoi accorciarlo su un solo fotogramma, perché poi improvvisamente scatteranno nell'aria - quindi qui, avendo un desiredLength è abbastanza breve da non toccare il suolo e a currentLength che si avvicina rapidamente desiredLength ti otterrà l'autorizzazione che desideri.

L'avatar è su

Se il tuo avatar è una figura umana, non ha molto senso per loro apparire costantemente perfettamente verticali mentre oscillano. Orientandoli in modo che appaiano come se fossero appesi alla corda - quindi sono capovolti se fanno un ciclo, ad esempio - potrebbe apparire come questo in Unity:

 Vector myUp = (avatar.position - tetherPoint); avatar.rotation = Quaternion.LookRotation (avatar.rotation.forward, myUp);

Questo lascerà l'avatar oscillare all'indietro. Puoi anche usare la velocità dell'avatar per la loro avanzata (è quello che faccio) - o lasciarli girare pazzamente ...

Avvolgendo le cose

Nel mondo reale, le corde avvolgono le cose. Un modo rapido per simulare che nel codice è di raycast lungo la corda virtuale ogni fotogramma, e se colpisce qualcosa, creare un nuovo punto di attacco dove si interseca. Questo non avrà un aspetto corretto se l'avatar torna indietro su una corda non appiccicosa, ma va bene per un fascio appiccicoso di rete, lingua o pinza.

Modificando il modo in cui i tuoi avvolgi corda può avere un grande impatto sul divertimento. Improvvisamente avvolgendo un affioramento può prendere il giocatore di sorpresa e renderli frustrati. Avevamo una soluzione in tre passaggi in Spider-Man 2: se eri troppo vicino all'affioramento, il web si rompeva; se tu fossi in una distanza media, il web si avvolgerebbe; e se fossi lontano, la rete passerebbe.


Considerazioni per il 3D

La cosa più difficile di portare questa meccanica 2D in 3D è prendere in considerazione l'interfaccia per il giocatore - come scelgono i punti nel mondo da cui passare. Giochi diversi usano metodi diversi per scegliere un punto del genere. Ratchet & Clank ha punti fissi nel mondo che puoi cimentarti; con il mod del rampino di Quake e il comando Bionic: riarmato puntate la fotocamera verso ciò a cui volete attaccare; Spider-Man 2 e Energy Hook proiettano i raggi rispetto al personaggio, e dove i raggi intersecano la geometria fisica che è il punto in cui si attaccano.


Quasi tutti questi metodi implicano il raycasting contro la geometria fisica del mondo, sia che si tratti della linea della telecamera o del personaggio fino al clic del mouse: l'intersezione del raycast determina il tuo nuovo tetherpoint.

Ad esempio, ecco un raycast per guardare il mouse che potrebbe essere utile per un gioco in prima persona:

 RaycastHit wallData; if (Physics.Raycast (camera.position, camera.forward, out wallData, maximumTetherLength)) amITethered = true; tetherPoint = wallData.point; tetherLength = Vector3.Distance (wallData.point, avatar.position); 

Bumping in Stuff

Bumping su muri e simili tende anche ad accadere molto più spesso in un gioco 3D rispetto a un gioco 2D, specialmente quando sono le mura su cui ti stai legando. Ci sono una varietà di cose che puoi fare per renderlo meno fastidioso.

  • Lascia che il giocatore vada in aria: la fisica non ha molto da dire su questo, ma in qualche modo sembra giusto. Questa è una delle cose che abbiamo fatto in Spider-Man 2 e perché hai un jetpack in Energy Hook.
  • Divertiti con un'animazione: fai fare una sorta di flip o spin all'avatar quando colpiscono un muro, e poi sembra meno un errore e più come "intendevo farlo!"
  • Tenerli fuori dal muro: Ultimate Spider-Man ha fatto questo - se ti avvicini troppo a un muro, ti allontanerebbe delicatamente da esso. Sembra un po 'strano se lasci andare il bastone e lasci semplicemente che il tuo avatar si blocchi - si allontanerebbero dal muro con uno strano angolo - ma per il resto del gioco è stato un miglioramento. (Potresti avere il meglio di entrambi i mondi spingendo solo se il personaggio sta andando ad una certa velocità?)
  • Ricompensali per non colpire il muro in primo luogo: questa è la strategia Energy Hook - insegnare al giocatore ad evitare di colpire i muri, premiandoli per le oscillazioni pulite. Da un lato, li incoraggia ad oscillare graziosamente; d'altra parte, quando colpiscono il muro è molto più frustrante, perché perdono i loro punti stile.


Allora, cosa stai aspettando?

Vai avanti e crea i tuoi giochi swing, e fammi sapere cosa ti viene in mente! Non riesco mai ad avere abbastanza giochi oscillanti.

Spero che tu abbia trovato utile questo articolo. Se lo hai, ti preghiamo di supportare Energy Hook Kickstarter o votarlo su Steam Greenlight. Grazie!