Cum se construiește un sistem Time-Rewind Prince-of-Persia, Partea 1

Ce veți crea

În acest tutorial, vom construi un simplu joc în care jucătorul poate rewind progresul în unitate (poate fi adaptat și pentru a funcționa în alte sisteme). Această primă parte va intra în elementele de bază ale sistemului, iar următoarea parte o va schimba și o va face mult mai versatilă.

În primul rând, deși vom analiza ce jocuri folosesc acest lucru. Apoi ne vom uita la alte utilizări pentru această configurație tehnică, înainte de a crea în cele din urmă un mic joc pe care îl putem derula înapoi, ceea ce ar trebui să vă ofere o bază pentru propria dvs..

O demonstrație a funcționalității de bază

Veți avea nevoie de cea mai nouă versiune a Unity pentru acest lucru și ar trebui să aveți o experiență în acest sens. Codul sursă este, de asemenea, disponibil pentru descărcare dacă doriți să vă verificați propriul progres împotriva acestuia.

Gata? Sa mergem!

Cum a fost folosit înainte?

Printul Persiei: Nisipurile timpului este unul dintre primele jocuri care integrează într-adevăr un mecanic de rebobinare a timpului în joc. Când mori, nu trebuie doar să reîncărcați, ci mai degrabă să derulați jocul câteva secunde până când ați trăit din nou și să încercați imediat.

Printul Persiei: Nisipurile uitate. Nisipurile timpului Trilogia integrează în timp frumos jocul în timp real și evită reîncărcarea rapidă a imersiunii.

Acest mecanic nu este integrat doar în gameplay, ci și în narațiune și în univers, și este menționat în întreaga poveste.

Alte jocuri care folosesc aceste sisteme sunt Tresă, de exemplu, care este, de asemenea, centrat în jurul înfășurării timpului. Eroul Tracer în Overwatch are o putere care o resetează într-o poziție cu câteva secunde în urmă, în esență rebobinare timp, chiar și într-un joc multiplayer. GRILĂ-seria de jocuri de curse are, de asemenea, un instantaneu-mecanic, în cazul în care aveți o piscină mică de reîntoarcere în timpul unei curse, pe care o puteți accesa atunci când aveți un accident critic. Acest lucru previne frustrarea cauzată de accidente aproape de sfârșitul cursei, ceea ce poate fi deosebit de infurios.


Când ai un accident fatal GRILĂ veți avea șansa de a derula jocul într-un punct înainte de accident.

Alte utilizări

Dar acest sistem nu poate fi folosit doar pentru a înlocui economiile rapide. Un alt mod în care acest lucru este folosit este ghosting în jocuri de curse și multiplayer asincron.

Reluările

Repetările reprezintă o altă modalitate amuzantă de a utiliza această funcție. Acest lucru poate fi văzut în jocuri ca SUPER FIERBINTE, Viermi serie, și destul de mult majoritatea jocurilor sportive.

Remodelarea sporturilor funcționează la fel cum sunt prezentate pe televizor, unde o acțiune este arătată din nou, posibil dintr-un unghi diferit. Pentru aceasta, nu este înregistrat un videoclip, ci mai degrabă acțiunile utilizatorului, permițând reluării să utilizeze diferite unghiuri și fotografii ale camerei. Jocurile Worms utilizează acest lucru într-un mod plin de umor, unde sunt afișate niște ucide foarte comice sau eficiente într-o Replay Instant.

SUPERHOT înregistrează, de asemenea, mișcarea. Când ați terminat să jucați în jurul întregului dvs. progres, este apoi reluat, arătând câteva secunde de mișcare reală care sa întâmplat.

Super Meat Boy folosește acest lucru într-un mod distractiv. Când terminați un nivel, veți vedea o reluare a tuturor încercărilor anterioare, așezate una peste alta, culminând cu trecerea de finisare fiind ultima stânga în picioare.

Replayul de la sfârșitul nivelului în Super Meat Boy. Fiecare dintre încercările dvs. anterioare este înregistrată și apoi redată în același timp.

Timp de încercare Ghosts

Cursa-remanente este o tehnică în care concurezi pentru cel mai bun timp pe o pistă goală. Dar, în același timp, te descurci împotriva a fantomă, care este o mașină fantomatică, transparentă, care conduce exact modul în care ați alergat înainte la cea mai bună încercare. Nu vă puteți ciocni, ceea ce înseamnă că vă puteți concentra în continuare pe obținerea celui mai bun timp.

În loc să conduci singur, ajungi concura împotriva ta, ceea ce face distracțiile mult mai distractive. Această caracteristică apare în majoritatea jocurilor de curse, de la Nevoie de viteza serie la Diddy Kong Racing.

Cursează o fantomă în Trackmania Nations. Aceasta are dificultatea de argint, ceea ce înseamnă că voi primi medalia de argint dacă le bat. Observați suprapunerea modelelor auto, arătând că fantoma nu este corporală și că poate fi condusă.

Multiplayer-Fantome

Asynchronous Multiplayer-Ghosting este un alt mod de a utiliza această configurație. În această caracteristică rar utilizată, meciurile multiplayer sunt realizate prin înregistrarea datelor unui jucător, care trimite apoi alerga la un alt jucător, care poate lupta ulterior împotriva primul jucător. Datele sunt aplicate în același mod în care ar fi o fantomă de timp, doar că te lupți împotriva unui alt jucător.

O formă de acest lucru apare în Trackmania-jocuri, în care este posibilă lupta împotriva anumitor dificultăți. Acești jucători înregistrați vă vor da un adversar pentru a câștiga o anumită răsplată.

Film-editare

Puține jocuri oferă acest lucru de la get-go, dar folosit drept poate fi un instrument distractiv.Cetatea echipei 2 oferă un editor de redare încorporat, cu ajutorul căruia puteți crea propriile clipuri.

Editorul de replici de la Cetatea echipei 2. Odată înregistrate, un meci poate fi văzut din orice punct de vedere, nu doar al jucătorului.

Odată ce funcția a fost activată, puteți înregistra și urmări meciurile anterioare. Elementul vital este acela Tot este înregistrată, nu numai viziunea dvs. Aceasta înseamnă că poți să te miști în jurul lumii de joc înregistrate, să vezi unde e toată lumea, și au control asupra timpului.

Cum se construiește

Pentru a testa acest sistem, avem nevoie de un joc simplu în care să îl putem testa. Să creăm una!

Jucătorul

Creați un cub în scenă, acesta va fi caracterul jucătorului nostru. Apoi, creați un apel C # nou Player.cs și să adapteze Actualizați()-funcția de a arăta astfel:

void Actualizare () transform.Translate (Vector3.forward * 3.0f * Time.deltaTime * Input.GetAxis ("Vertical")); transforma.Rota (Vector3.up * 200.0f * Time.deltaTime * Input.GetAxis ("Orizontal")); 

Aceasta se va ocupa de deplasarea simplă prin intermediul tastelor săgeți. Atașați acest script la cubul jucătorului. Când te-ai lovit acum, ar trebui să te poți deplasa.

Apoi, înclinați aparatul foto astfel încât acesta să vadă cubul de sus, cu cameră pe partea sa, unde îl putem mișca. În cele din urmă, creați un avion pentru a acționa ca podea și să atribuiți diferite materiale fiecărui obiect, astfel încât să nu îl deplasăm în interiorul unui gol. Ar trebui să arate astfel:

Încearcă-l și ar trebui să poți deplasa cubul cu tastele WSAD și săgeți.

TimeController

Acum creați un nou script C # numit TimeController.cs și adăugați-l la un nou GameObject gol. Aceasta va face față înregistrării reale și reîncărcării ulterioare a jocului.

Pentru a face acest lucru, vom înregistra mișcarea caracterului jucătorului. Atunci când apăsăm butonul de derulare, vom adapta coordonatele jucătorului. Pentru a începe acest lucru, creați o variabilă pentru a ține jucătorul, astfel:

jucător public GameObject;

Și atribuiți player-obiect la slotul rezultat pe TimeController, astfel încât să poată accesa player-ul și datele sale.

Apoi trebuie să creăm o matrice pentru a ține datele jucătorului:

public ArrayList playerPoziții; void Start () playerPositions = nou ArrayList (); 

Ce vom face mai departe este înregistrarea continuă a poziției jucătorului. Vom păstra poziția în care jucătorul se afla în ultimul cadru, poziția în care jucătorul avea 6 cadre în urmă și poziția în care jucătorul a fost acum 8 secunde (sau oricât de lungă îl veți seta să înregistreze). Când am apăsat mai târziu un buton, vom merge înapoi prin gama noastră de poziții și îi vom atribui cadru cu cadru, rezultând o caracteristică de relanșare a timpului.

Mai întâi, să salvăm datele:

void FixedUpdate () playerPositions.Add (player.transform.position); 

În FixedUpdate ()-funcția pe care o înregistrăm. FixedUpdate () se utilizează în timp ce se execută la o constantă de 50 de cicluri pe secundă (sau orice ați setat), ceea ce permite un interval fix de înregistrare și setare a datelor. Actualizați()-funcția între timp rulează în funcție de numărul de cadre pe care le gestionează CPU, ceea ce ar face lucrurile mai dificile.

Acest cod va stoca poziția jucătorului fiecărui cadru în matrice. Acum trebuie să o aplicăm!

Vom adăuga un cec pentru a vedea dacă a fost apăsat butonul de derulare înapoi. Pentru aceasta avem nevoie de o variabilă booleană:

boolul public esteReversing = false;

Și o verificare în Actualizați()-funcția de a stabili dacă doriți să derulați înapoi modul de joc:

void Actualizare () if (Input.GetKey (KeyCode.Space)) isReversing = true;  altceva isReversing = false; 

Pentru a face jocul să ruleze înapoi, vom aplica datele în loc de înregistrareNoul cod pentru înregistrarea și aplicarea poziției jucătorului ar trebui să arate astfel:

void FixedUpdate () if (! esteReversing) playerPositions.Add (player.transform.position);  altceva player.transform.position = (Vector3) playerPozitii [playerPositions.Count - 1]; playerPositions.RemoveAt (jucatorPoziții.Count - 1); 

Și întreaga TimeController-script ca acesta:

utilizând UnityEngine; utilizând System.Collections; clasa publica TimeController: MonoBehavior public GameObject player; public ArrayList playerPoziții; boolul public esteReversing = false; void Start () playerPositions = nou ArrayList ();  void Actualizare () if (Input.GetKey (KeyCode.Space)) isReversing = true;  altceva isReversing = false;  void FixedUpdate () dacă (! esteReversing) playerPositions.Add (player.transform.position);  altceva player.transform.position = (Vector3) playerPozitii [playerPositions.Count - 1]; playerPositions.RemoveAt (jucatorPoziții.Count - 1); 

De asemenea, nu uitați să adăugați un cec la jucător-clasa pentru a vedea dacă TimeController se învârte în prezent sau nu și se mișcă numai când nu inversează. În caz contrar, ar putea crea un comportament buggy:

utilizând UnityEngine; utilizând System.Collections; public class Jucător: MonoBehavior privat TimeController timeController; void Start () timeController = FindObjectOfType (typeof (TimeController)) ca TimeController;  void Actualizare () if (! timeController.isReversing) transform.Translate (Vector3.forward * 3.0f * Time.deltaTime * Input.GetAxis ("Vertical")); transforma.Rota (Vector3.up * 200.0f * Time.deltaTime * Input.GetAxis ("Orizontal"));  

Aceste linii noi vor găsi automat TimeController-obiecte în scenă la pornire și verificați-l în timpul execuției pentru a vedea dacă jocul este în joc sau când îl rebobinăm. Putem controla doar caracterul atunci când momentan nu ne inversăm timpul.

Acum ar trebui să puteți să vă mișcați în jurul lumii și să derulați mișcarea prin apăsarea spațiului. Dacă descărcați pachetul de instalare atașat la acest articol și deschideți-l TimeRewindingFunctionality01 îl puteți încerca!

Dar așteptați, de ce cubul nostru simplu de jucători continuă să privească în ultima direcție în care le-am lăsat? Pentru că nu am reușit să înregistrăm rotația!

Pentru asta, aveți nevoie de o altă matrice pentru a păstra valorile de rotație, pentru ao instanța la început și pentru a salva și aplica datele în același mod în care am manipulat datele de poziție.

utilizând UnityEngine; utilizând System.Collections; clasa publica TimeController: MonoBehavior public GameObject player; public ArrayList playerPoziții; public ArrayList playerRotații; boolul public esteReversing = false; void Start () playerPositions = nou ArrayList (); playerRotations = nou ArrayList ();  void Actualizare () if (Input.GetKey (KeyCode.Space)) isReversing = true;  altceva isReversing = false;  void FixedUpdate () dacă (! esteReversing) playerPositions.Add (player.transform.position); playerRotations.Add (player.transform.localEulerAngles);  altceva player.transform.position = (Vector3) playerPozitii [playerPositions.Count - 1]; playerPositions.RemoveAt (jucatorPoziții.Count - 1); player.transform.localEulerAngles = (Vector3) jucatorRotații [playerRotations.Count - 1]; playerRotations.RemoveAt (playerRotări.Count - 1); 

Încearcă! TimeRewindingFunctionality02 este versiunea îmbunătățită. Acum, cubul jucătorului nostru se poate mișca înapoi în timp și va arăta la fel cum a procedat atunci când a fost în acel moment.

Concluzie

Am construit un simplu joc prototip cu un sistem de rebobinare deja folosit, dar este departe de a fi făcut încă. În următoarea parte a acestei serii vom face mult mai stabil și mai versatil și vom adăuga câteva efecte înguste. 

Iată ce mai trebuie să facem:

  • Doar înregistrați fiecare cadru ~ 12 și interpolați între cele înregistrate pentru a salva sarcina imensă a datelor
  • Înregistrați doar ultimele poziții și rotații de 75 de jucători pentru a vă asigura că matricea nu devine prea greoaie și jocul nu se prăbușește

De asemenea, ne vom uita la modul în care extindeți acest sistem pe lângă caracterul jucătorului:

  • Înregistrați mai mult decât playerul
  • Adăugați un efect pentru a însemna că reîncărcarea se întâmplă (cum ar fi neclaritatea VHS)
  • Utilizați o clasă personalizată pentru a menține poziția jucătorului și rotația în loc de matrice