Swinging Physics for Player Movement (Soos gesien in Spider-Man 2 en Energy Hook)
by Jamie Fristrom 5 Jun 2013
ProgrammingPlatform AgnosticUnity 3D
Hi! Ek is Jamie Fristrom van Happion Laboratories. Jy kan my onthou van sulke speletjies soos Die By Die Swaard, Spider-Man 2, en Schizoid ... wat almal, in een of ander vorm, tou ingesluit het. Ek het onlangs gewerk aan 'n speletjie genaamd Energy Hook - onlangs van stapel gestuur op Kickstarter - wat alles oor tou betref. (Wel, dit gaan alles oor jou graviton-aangedrewe grappelstraal.)
Ek gaan bespreek hoe ek graag 'n tou-swaaiende spelmeganikus wil implementeer. Toe ek met Energy Hook begin werk het, het ek alles met my eie pasgemaakte kode gedoen. Ek glo dat dit moontlik is om eenvoudig in Unity te gaan en die Configurable Joint gebruik om baie soortgelyke dinge te doen, maar destyds was dit nie beskikbaar nie. Ek is redelik seker dit is in elk geval die regte oproep, want dit gee my beheer oor alles - en ek kan dit met jou deel.
Ek het al die nuwe funksies bedek en het jou gewys hoe om dit te gebruik om produktiwiteit te verhoog beperkings - is eintlik redelik eenvoudig. (Hoop jy is nie teleurgesteld as jy sien wat onder die kap is nie.) Dit werk dieselfde as jy 'n 2D-spel of 3D-speletjie maak. Dis net dat die vektore anders is, dus begin ek met 2D en dan Bespreek sommige plooie wanneer jy na drie dimensies gaan.
Hierdie artikel veronderstel ook dat jy 'n speletjie enjin soos Unity gebruik wat baie van die werk vir jou kan doen, soos raikasting teen geometrie en die oriëntering van 'n karakter, met eenvoudige funksieoproepe. As jy jou eie enjin gebruik, moet jy self die wiskunde self doen.
Physical Simulasies vs Ingemaakte Beweging
Daar is twee maniere waarop spel simulasies dikwels werk. Die meeste derde persoon speletjies het alles ingemaak; ingemaakte animasies en ingemaakte bewegings sodat alles perfek lyk, die karakter se voete gly nie reguit van die animator se animasieprogram nie. Die alternatief is 'n baie fisiese simulasie. Jy simuleer fisika: versnelling, snelheid, swaartekrag. Baie eerstespeler-speletjies doen dit, maar derdepersoonspele is geneig om dit te vermy, want dit is baie makliker om die karakter se voete te hê. skuif en die fisiese dinge kom nie ooreen met die animasie nie.
As jy 'n nie-ingemaakte tou swaai wil maak (in teenstelling met 'n ingemaakte tou swaai, soos gesien in die heel eerste Pitfall, of die vroeë Spider-Man speletjies soos Neversoft's op die PSX), 'n tou-swaai wat eintlik 'n fisiese simulasie is en dus dalk vryheid en nuansheid en die viscerale gevoel het wat werklike swaartekrag en momentum jou kan gee, dan gaan jy dit die tweede manier doen - alles moet 'n fisiese simulasie wees en vermy ingemaakte dinge wat die karakter se momentum doodmaak. Dan, sal alles vloei.
Dis hoe ek dinge doen met Energy Hook.
Daar is 'n klomp artikels daar oor hoe om fisika te simuleer - hier is een met 'n koel Flash demo ingebou. Jy kan Euler integrasie of Verlet integrasie doen, dit maak nie saak nie. (Ek sal jou nie hieroor oor Euler versus Verlet leer nie, maar laat my net sê dat die konsepte nie so vreesaanjaend is as wat hulle klink nie.)
Kom ons neem aan dat ons die Euler integrasie van die been doen. Ons karakter se spel tydstip kan so lyk, waar die versnelling bepaal word deur swaartekrag en hoe jy op die stok stoot:
avatar.velocity = avatar.velocity + avatar.acceleration * deltaT;
avatar.position = avatar.position + avatar.velocity * deltaT;
(Side note: dit is eintlik 'n rowwe benadering - jy kan 'n beter, minder framerate-afhanklike benadering met avatar.position = avatar.position + (avatar.oldvelocity avatar.position = avatar.position + (avatar.oldvelocity + avatar.velocity) * deltaT / 2.0f, en Jy kan 'n nabye perfekte-om-simulasie kry met iets soos hierdie - maar jou spelers sal waarskynlik nie agterkom nie.)
Simuleer Tearable Cloth and Ragdolls Met Simple Verlet Integration
Hoe om 'n aangepaste 2D Physics Ejin
Jou speletjie het waarskynlik 'n stelsel om met wêreldgeometrie te bots. Dit lyk waarskynlik so iets:
Vector testPosition = avatar.position + avatar.velocity * deltaT;
if( RayCast( position, testPosition, out intersection ))
// we went through a wall, let's pull the character back,
// using the normal of the wall
// with a 1-unit space for breathing room
testPosition = intersection + intersection.normal;
Wat gebeur met jou avatar se snelheid wanneer hulle 'n hindernis tref? Dit maak nie sin vir jou avatar om dieselfde snelheid deur die muur te handhaaf nie. Sommige speletjies kan jou weiering, met die normaal van waar jy gekruis het om jou snelheid te weerspieël; ander speletjies kan jou laat gly langs die muur; ander sal êrens tussenin wees. Kom ons kyk na die kode om langs 'n muur te gly:
avatar.velocity = (testPosition - avatar.position)/deltaT;
avatar.position = testPosition;
(As jy Verlet-integrasie doen, waar elke raam jy alreeds bepaal deur eenvoudig na die vorige posdata te kyk, is hierdie stap alreeds vir jou gedoen.)
Ook, videogames is die gelukkige dinge wat hulle is, en jy sal waarskynlik dikwels vind dat jou karakter se posisie skielik van een raam na die volgende in sekere hoekgevalle snap. Wanneer dit gebeur, sal hulle snelheid deur die dak gaan. My oplossing hiervoor is eenvoudig 'n hack: kyk of hul snelheid te erg raak en regmaak as dit wel gebeur.
Wat doen die kode wanneer jy 'n muur in 'n hoek slaan? Die eerste raam, dit verander jou snelheid dramaties as jy die muur tref, maar dit stoot jou nog steeds deur die muur. Die volgende raam, jou avatar word weer opgedateer in die muur en dan weer teruggedruk, maar nou is die snelheid die avatar se nuwe posisie, gly langs die muur, minus sy ou posisie, teen die muur, so dit is parallel aan die muur .
Dit is 'n groot oversimplisering van wat in die regte wêreld gebeur wanneer een voorwerp bots met 'n ander, maar die meeste van jou spelers sal nie oplet of versorg nie.
Op hierdie punt, al is, ons het ons avatar se posisie en snelheid met die mure en vloere van ons spel suksesvol beperk. So nou is ons gereed.
Beperking Van Tethers van Mure
Stel jou nou voor dat jou avatar reeds deur 'n virtuele tou aan 'n virtuele punt geheg is. Wat ons betref, kan ons dit net oorweeg as 'n onsigbare sirkelvormige of sferiese muur. Ons kan botsing toets deur te sien of u te ver weg van die middelpunt van die sirkel gekry het, en die avatar terugtrek.
if( amITethered )
if (testPosition - tetherPoint ).Length() > tetherLength )
// we're past the end of our rope
// pull the avatar back in.
testPosition = (testPosition - tetherPoint).Normalized() * tetherLength;
Nou, dieselfde snelheid sbepalings wat ons op die mure laat gly sal ons ook in die binnekant van hierdie virtuele sirkel of bol laat gly.
Swinging Physics: Falling with a Tether - Raam 1
Swinging Physics: Falling with a Tether - Raam 2
Sommige Subtiliteit en Nuance
Op hierdie punt het jy 'n swaaiende spel. Maar daar gaan waarskynlik 'n paar dinge wees wat die spel vir jou spelers vermaak, en dit is waar 'n bietjie hacking dinge beter kan maak.
Afhangende van jou spel, en of dit 'n tou of 'n elastiese web of 'n grypstraal moet simuleer, kan jy verskillende benaderings tot slap en springigheid hê. Jy kan baie dinge simuleer deur die tetherLength. As jy uit jou veerkragtige web of grypstraal wil uitbreek, kan jy die tetherLength as die speler nader aan die tether punt kom:
tetherLength = (avatar.position - tetherPoint).Length();
Maar as dit 'n nonelastic tou is, laat jy die tetherLength onaangeraak.
Vir springigheid, jy kan 'n begeerLength dit is vas en a huidigLength wat voortdurend probeer om die begeerLength - dit sal ook nuttig wees vir ons volgende stap:
Maar Ek wil nie slaan nie die Grond!
Wat as jou avatar op 'n lae plek begin en probeer swaai? Dit is redelik duidelik dat hulle nie baie ver kry nie. 'N vinnige oplossing vir dit is om te kyk hoe hoog bo die grond die punt waarna hulle wil swaai, is en verkort hul lengte sodat hulle die grond kan skoonmaak.
Jy kan dit nie net oor een raam verkort nie, want dan sal hulle skielik in die lug klim - so hier, met 'n begeerLength dit is kort genoeg om nie die grond te raak nie en a huidigLength wat vinnig nader beggerLength sal jou die uitklaring kry wat jy wil hê.
Die Avatar's Up
As jou avatar 'n humanistiese figuur is, maak dit nie veel sin dat hulle voortdurend perfek vertikaal verskyn nie, aangesien hulle swaai. Oriënteer hulle sodat hulle lyk of hulle van die tou hang - so hulle is onderstebo as hulle byvoorbeeld 'n lus doen - kan so in Unity lyk:
Vector myUp = (avatar.position - tetherPoint);
avatar.rotation = Quaternion.LookRotation( avatar.rotation.forward, myUp );
Dit sal die avatar agteruit laat swaai. Jy kan ook die avatar se snelheid gebruik vir hul vorentoe (dit is wat ek doen) - of laat hulle krank draai ...
Wrapping Rondom Dinge
In die regte wêreld draai toue om dinge. 'N Vinnige manier om dit in jou kode te simuleer, is om elke raam langs die virtuele tou te raik, en as dit iets tref, maak 'n nuwe aanhegtingspunt waar dit sny. Dit sal nie regkyk as die avatar dan weer op 'n onbelaste tou swaai nie, maar is goed vir 'n taai web, tong of grappelbalk.
Die manier waarop jou tou wikkel, kan 'n groot impak op pret hê. Skielik om 'n outcroping te draai, kan die speler verras word en gefrustreer word. Ons het 'n drie-stap-oplossing in Spider-Man 2 gehad: as jy te naby aan die outcropping was, sou die web breek; As jy in 'n middelafstand was, sou die web wikkel; En as jy ver weg was, sou die web net gaan.
Oorwegings vir 3D
Die moeilikste ding om hierdie 2D-monteur na 3D te bring, oorweeg die koppelvlak vir die speler - hoe kies hulle punte in die wêreld om van te swaai. Verskillende speletjies gebruik verskillende metodes om so 'n punt te kies. Ratchet & Clank het vaste punte in die wêreld wat jy kan worstel; Met die Quake grappling-haak mod en Bionic Commando: Met jou omring, wys die kamera op wat jy wil heg; Spider-Man 2 en Energy Hook gooi strale uit relatief tot die karakter, en waar die strale die fisiese geometrie sny dit is die punt waar jy heg.
Byna al hierdie metodes behels raycasting teen die wêreld se fisiese meetkunde, of dit langs die lyn is die kamera of van die karakter tot die punt van die muis kliek - die snyding van die raycast bepaal jou nuwe baanpunt.
Byvoorbeeld, hier is 'n muis-look raycast wat goed kan wees vir 'n eerste persoon spel:
if( Physics.Raycast( camera.position, camera.forward, out wallData, maximumTetherLength ))
amITethered = true;
tetherPoint = wallData.point;
tetherLength = Vector3.Distance( wallData.point, avatar.position );
Stamp In Stuff
Stamp in mure en dies meer is ook geneig om meer dikwels in 'n 3D-spel as 'n 2D-spel te gebeur, veral wanneer dit die mure is waaraan jy jouself verbind. Daar is 'n verskeidenheid dinge wat jy kan doen om dit minder irriterend te maak.
Laat die speler in die lug stuur: fisika het nie veel om hieroor te sê nie, maar dit voel een of ander manier reg. Dit is een van die dinge wat ons in Spider-Man 2 gedoen het, en hoekom kry jy 'n jetpack in Energy Hook.
Speel 'n koel animasie: het die avatar 'n soort flip of spin wanneer hulle 'n muur slaan, en dan voel dit minder soos 'n fout en meer soos " Ek het dit bedoel!"
Hou hulle van die muur af: Ultimate Spider-Man het dit gedoen - As jy te naby aan 'n muur gekom het, sal dit jou saggies druk. Dit lyk 'n bietjie vreemd as jy die stok loslaat en net laat jou avatar daar hang - hulle sal op 'n vreemde hoek van die muur wegdryf - maar vir die res van die wedstryd was dit 'n verbetering. (Jy kan moontlik die beste van albei wêrelde hê deur net weg te stoot as die karakter 'n sekere spoed gaan?)
Beloon hulle om nie die muur in die eerste plek te slaan nie: Dit is die Energy Hook-strategie - leer die speler om mure te vermy, deur hulle vir skoon swaai te beloon. Aan die een kant, dit moedig hulle aan om mooi te swaai; aan die ander kant, wanneer hulle die muur tref, is dit soveel frustrerend, omdat hulle hul stylpunte verloor.
So Waarvoor Wag Jy?
Gaan voort en maak jou eie swaaiwedstryde, en laat my weet wat jy opkom! Ek kan nooit genoeg kry van swaaiende speletjies nie.
Ek hoop jy het hierdie artikel nuttig gevind. As jy het, ondersteun asseblief die Energy Hook Kickstarter of vote it up on Steam Greenlight. Dankie!
Aka Happion Labs. Currently working on Energy Hook. Check out my blog or follow me on Twitter!