Hej! Jag är Jamie Fristrom of Happion Laboratories. Du kommer kanske ihåg mig från sådana spel som Die By the Sword, Spider-Man 2, och Schizoid ... som alla, i en eller annan form, inkluderade rep. Jag har nyligen arbetat med ett spel som heter Energy Hook - som nyligen lanserades på Kickstarter - som handlar om rep. (Tja, det handlar bara om din graviton-drivna gripbalk, ändå.)
Jag ska diskutera hur jag gillar att implementera en rep-swinging gameplay mekaniker. När jag började arbeta med Energy Hook gjorde jag mest allt med min egen kod. Jag tror att det är möjligt att helt enkelt gå in i Unity och använda Configurable Joint för att göra några mycket liknande saker, men då var det inte tillgängligt. Jag är ganska säker på att det här har varit rätt samtal, ändå, för att det ger mig kontroll över allt - och jag kan dela den med dig.
Grunden för att göra svängande hur jag gjorde - med begränsningar - är faktiskt ganska enkelt. (Hoppas du är inte besviken när du ser vad som ligger under huven.) Det fungerar inte heller om du gör ett 2D-spel eller 3D-spel, det är bara att vektorerna är olika, så jag börjar med 2D och sedan diskutera några rynkor när du går till tre dimensioner.
Den här artikeln förutsätter också att du använder en spelmotor som Unity som kan göra mycket för dig, som att rita mot geometri och orientera ett tecken, med enkla funktionssamtal. Om du använder din egen motor kan du behöva göra det själv matta.
Det finns två sätt att spela simuleringar fungerar ofta. De flesta tredje person spel har konserver allt; konserverade animationer och konserverade rörelser så att allt ser perfekt ut, karaktärens fötter glider inte direkt från animatörens animationsprogram till oss. Alternativet är en mycket mer fysisk simulering - du simulerar fysik: acceleration, hastighet, tyngdkraft - många förstaspel gör det här, men spel från tredje man tenderar att undvika det, eftersom det är mycket lättare att få karaktärens fötter glida och de fysiska sakerna matchar inte animeringen.
Om du vill göra ett icke-konservatstångssving (i motsats till ett konserverat repsvängning, sett i det allra första fallet, eller de tidiga Spider-Man-spelen som Neversoft på PSX), en rep-swing som faktiskt är en fysisk simulering och kan därför kanske ha frihet och nyans och den viscerala känslan som verklig tyngdkraft och momentum kan ge dig, då kommer du att vilja göra det andra sättet - ha allting vara en fysisk simulering och undvik att göra konserverade saker som dödar karaktärens momentum. Då kommer allt att flöda.
Det är så jag gör saker med Energy Hook.
Det finns massor av artiklar där ute om hur man simulerar fysiken - här är en med en cool Flash-demo inbyggd. Du kan göra Euler-integration eller Verlet-integration, det spelar ingen roll någon roll. (Jag kommer inte att lära dig om Euler vs Verlet här, men låt mig bara säga att koncepten inte är så skrämmande som de låter.)
Låt oss anta att vi gör den enkla Euler-integrationen. Vår karaktärs timestep kan se ut så här, där acceleration bestäms av tyngdkraften och hur du trycker på pinnen:
avatar.velocity = avatar.velocity + avatar.acceleration * deltaT; avatar.position = avatar.position + avatar.velocity * deltaT;
(Sidnot: Detta är faktiskt en grov approximation - du kan få en bättre, mindre frameratberoende approximation med avatar.position = avatar.position + (avatar.oldvelocity + avatar.velocity) * delta / 2.0f
, och du kan få en perfekt simulering med något sådant - men dina spelare kommer nog inte att märka.)
Ditt spel har förmodligen ett system för att kollidera med världsgeometri. Det ser nog ut som om det här:
Vector testPosition = avatar.position + avatar.velocity * deltaT; Vektor korsning om (RayCast (position, testPosition, utkorsning)) // vi gick genom en vägg, låt oss dra teckenet tillbaka, // med hjälp av väggens norm // med ett 1-rums utrymme för andningsrum testPosition = korsning + korsning.normal;
Vad händer med din avatar hastighet när de slår ett hinder? Det är inte meningsfullt för din avatar att behålla samma hastighet genom väggen. Vissa spel kan studsa dig med hjälp av det normala av var du kryssade för att reflektera din hastighet; Andra spel kan låta dig glida längs väggen; andra kommer att vara någonstans däremellan. Låt oss titta på kod för att glida längs en vägg:
avatar.velocity = (testposition - avatar.position) / deltaT; avatar.position = testposition;
(Om du gör Verlet integration, där varje ram du redan bestämmer hastighet helt enkelt genom att titta på tidigare positionsdata, är detta steg redan gjort för dig.)
Även videogames är de lyckliga sakerna de kommer, du kommer troligen ofta att upptäcka att din karaktärs position plötsligt plötsligt från en ram till nästa i vissa hörnfall. När detta händer, går deras hastighet genom taket. Min lösning för det är helt enkelt ett hack: kontrollera om deras hastighet blir för extrem och fixa den om den gör det.
Vad gör den koden när du träffar en vägg i vinkel? Den första ramen, det ändrar din hastighet dramatiskt när du slår på väggen, men det pressar dig fortfarande genom väggen. Nästa ram, din avatar blir uppdaterad till väggen igen och sedan skjuts ut igen, men nu är hastigheten avatarens nya position, glidde sig längs väggen, minus sin gamla position mot väggen, så den är parallell med väggen.
Det här är en enorm förenkling av vad som händer i den verkliga världen när ett objekt kolliderar med en annan, men de flesta av dina spelare kommer inte att märka eller bryr sig.
Vid denna tidpunkt har vi dock framgångsrikt begränsat vår avatars position och hastighet med våra spelets väggar och golv. Så nu är vi redo.
Så nu föreställ dig att din avatar redan är kopplad av ett virtuellt rep till en virtuell punkt. Såvitt vi är berörda kan vi helt enkelt betrakta det som en osynlig cirkulär eller sfärisk vägg. Vi kan testa kollision genom att se om du har blivit för långt borta från mitten av cirkeln och dra tillbaka avataren.
if (testPosition - tetherPoint) .Length ()> tetherLength) // vi är över slutet av vårt rep // dra tillbaka avataren. testPosition = (testPosition - tetherPoint) .Normalized () * tetherLength;
Nu, samma hastighetsjustering som gjorde oss glida längs väggar gör oss också glida längs insidan av denna virtuella cirkel eller sfär.
Vid denna tid har du ett svängande spel. Men det kommer förmodligen att vara några saker om det som blir väldigt roliga för dina spelare, och det är här en liten hackning kan göra saker bättre.
Beroende på ditt spel, och om det ska simuleras en rep eller en elastisk webb eller en gripbalk, kan du ha olika tillvägagångssätt för slakhet och springiness. Du kan simulera en hel del saker genom att finjustera tetherLength
. Om du vill slacka ut ur din fjädrande web eller grapple beam, kan du förkorta tetherLength
när spelaren kommer närmare tether-punkten:
tetherLength = (avatar.position - tetherPoint). Längd ();
Men om det är ett nonelastiskt rep, skulle du lämna tetherLength
oberörd.
För springiness kan du ha en desiredLength
det är fast och a currentLength
som ständigt försöker närma sig desiredLength
- Detta kommer också att vara användbart för vårt nästa steg:
Vad händer om din avatar börjar på en låg plats och försöker svänga? Det är ganska uppenbart att de inte kommer bli väldigt långt. En snabb lösning för det är att kontrollera hur högt över marken den punkt som de vill svänga från är och förkorta längden på deras tätning så att de kommer att rensa marken.
Du kan inte bara förkorta den över en ram, för då kommer de plötsligt att snäppa in i luften - så här, ha en desiredLength
det är tillräckligt kort för att inte röra marken och a currentLength
som snabbt närmar sig desiredLength
kommer att få dig det spelrum du vill ha.
Om din avatar är en humanistisk siffra, är det inte så mycket för dem att de uppträder ständigt perfekt vertikalt medan de svänger. Orientera dem så att de ser ut som om de hänger från repet - så de är upp och ner om de gör en slinga, till exempel - kan se ut så här i Unity:
Vector myUp = (avatar.position - tetherPoint); avatar.rotation = Quaternion.LookRotation (avatar.rotation.forward, myUp);
Detta låter avatar svänga bakåt. Du kan också använda avatarens hastighet för deras framåt (det är vad jag gör) - eller låt dem snurra vildt ...
I den verkliga världen lindar rep runt saker. Ett snabbt sätt att simulera det i din kod är att raycast längs det virtuella repet varje ram, och om det träffar något, skapa en ny bilaga punkt där den skärs. Detta kommer inte att se ut om avataren svänger tillbaka på ett ojämnt rep, men det går bra för en klibbig webb-, tung- eller gripbalk.
Tweaking hur ditt rep wraps kan ha en stor inverkan på roligt. Plötsligt omsluta en outcropping kan spelaren bli överraskad och göra dem frustrerade. Vi hade en trestegslösning i Spider-Man 2: om du var för nära den outcropping skulle webben bryta; Om du befann dig i mellanavstånd skulle nätet gå ihop; och om du var långt bort skulle webben bara gå igenom.
Det svåraste med att föra denna 2D-mekaniker till 3D överväger gränssnittet för spelaren - hur de väljer punkter i världen att svänga från. Olika spel använder olika metoder för att välja en sådan punkt. Ratchet & Clank har fasta poäng i världen du kan gripa; med Quake grappling-hook mod och Bionic Commando: Rearmed dig pekar kameran på det du vill fästa på; Spider-Man 2 och Energy Hook gjuter ut i förhållande till karaktären, och där strålarna skär den fysiska geometrin som är den punkt där du bifogar.
Nästan alla dessa metoder involverar raykasting mot världens fysiska geometri, oavsett om den ligger längs linjen i kameran eller från tecknet till musklickets punkt - skärningspunkten för raycasten bestämmer din nya tetherpoint.
Till exempel, här är en mus-look raycast som kan vara bra för ett första personspel:
RaycastHit wallData; om (Physics.Raycast (camera.position, camera.forward, out wallData, maximumTetherLength)) amITethered = true; tetherPoint = wallData.point; tetherLength = Vector3.Distance (wallData.point, avatar.position);
Bumpning i väggar och liknande tenderar också att hända mycket oftare i ett 3D-spel än ett 2D-spel, speciellt när det är de väggar som du knyter dig till. Det finns en mängd olika saker du kan göra för att göra detta mindre irriterande.
Gå ut och gör dina egna svängande spel, och låt mig veta vad du kommer med! Jag kan aldrig få nog av svängande spel.
Jag hoppas att du har hittat den här artikeln användbar. Om du har, vänligen stödja Energy Hook Kickstarter eller rösta upp det på Steam Greenlight. Tack!